Merge remote-tracking branch 'origin/master'
diff --git a/Makefile b/Makefile
index b303513..b7f0053 100644
--- a/Makefile
+++ b/Makefile
@@ -4,77 +4,74 @@
OBJS += objects/pflash/arm_io.o
OBJS2 = progress.o ast-sf-ctrl.o libflash.o libffs.o arm_io.o
OBJS3 = obj/progress.o obj/ast-sf-ctrl.o obj/libflash.o obj/libffs.o obj/arm_io.o
-LIBS = ./bin
-OFLAGS =-L$(LIBS) -lopenbmc_intf
-HOME = .
-CFLAGS=$(shell pkg-config --libs --cflags gio-unix-2.0 glib-2.0)
-#CFLAGS = -pthread -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lgio-2.0 -lgobject-2.0 -lglib-2.0
+INCLUDES=$(shell pkg-config --cflags gio-unix-2.0 glib-2.0) -Iincludes -Iobjects/pflash -I.
+LIBS=$(shell pkg-config --libs gio-unix-2.0 glib-2.0) -Lbin -lopenbmc_intf
%.o: interfaces/%.c
- $(CC) -c -fPIC -o obj/$@ $< -I$(HOME) -I$(HOME)/includes $(CFLAGS)
+ $(CC) -c -fPIC -o obj/$@ $< $(CFLAGS) $(INCLUDES)
%.o: objects/%.c
- $(CC) -c -o obj/$@ $< -L$(LIBS) -I$(HOME) -I$(HOME)/includes -I$(HOME)/objects/pflash $(CFLAGS)
+ $(CC) -c -o obj/$@ $< $(LIBS) $(CFLAGS) $(INCLUDES)
%.o: includes/%.c
- $(CC) -c -o obj/$@ $< -L$(LIBS) -I$(HOME) -I$(HOME)/includes -I$(HOME)/objects/pflash $(CFLAGS)
+ $(CC) -c -o obj/$@ $< $(LIBS) $(CFLAGS) $(INCLUDES)
%.o: objects/pflash/%.c
- $(CC) -c -o obj/$@ $< -I$(HOME) -I$(HOME)/objects/pflash $(CFLAGS)
+ $(CC) -c -o obj/$@ $< $(CFLAGS) $(INCLUDES)
%.o: objects/pflash/libflash/%.c
- $(CC) -c -o obj/$@ $< -I$(HOME) -I$(HOME)/objects/pflash $(CFLAGS)
+ $(CC) -c -o obj/$@ $< $(CFLAGS) $(INCLUDES)
setup:
- mkdir obj
+ mkdir -p obj
clean:
rm -rf obj
libopenbmc_intf: openbmc_intf.o
- $(CC) -shared -o bin/$@.so obj/openbmc_intf.o $(CFLAGS)
+ $(CC) -shared -o bin/$@.so obj/openbmc_intf.o $(LDFLAGS)
-power_control: power_control_obj.o gpio.o
- $(CC) -o bin/$@.exe obj/gpio.o obj/power_control_obj.o $(OFLAGS) $(CFLAGS)
+power_control: power_control_obj.o gpio.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/gpio.o obj/power_control_obj.o $(LDFLAGS) $(LIBS)
-led_controller: led_controller.o gpio.o
- $(CC) -o bin/$@.exe obj/gpio.o obj/led_controller.o $(OFLAGS) $(CFLAGS)
+led_controller: led_controller.o gpio.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/gpio.o obj/led_controller.o $(LDFLAGS) $(LIBS)
-sensor_ambient: sensor_threshold.o sensor_temperature_ambient_obj.o
- $(CC) -o bin/$@.exe obj/sensor_threshold.o obj/sensor_temperature_ambient_obj.o $(OFLAGS) $(CFLAGS)
+sensor_ambient: sensor_threshold.o sensor_temperature_ambient_obj.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/sensor_threshold.o obj/sensor_temperature_ambient_obj.o $(LDFLAGS) $(LIBS)
-button_power: button_power_obj.o gpio.o
- $(CC) -o bin/$@.exe obj/button_power_obj.o obj/gpio.o $(OFLAGS) $(CFLAGS)
+button_power: button_power_obj.o gpio.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/button_power_obj.o obj/gpio.o $(LDFLAGS) $(LIBS)
-control_host: control_host_obj.o gpio.o
- $(CC) -o bin/$@.exe obj/gpio.o obj/control_host_obj.o $(OFLAGS) $(CFLAGS)
+control_host: control_host_obj.o gpio.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/gpio.o obj/control_host_obj.o $(LDFLAGS) $(LIBS)
-flash_bios: flash_bios_obj.o
- $(CC) -o bin/$@.exe obj/flash_bios_obj.o $(OFLAGS) $(CFLAGS)
+flash_bios: flash_bios_obj.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/flash_bios_obj.o $(LDFLAGS) $(LIBS)
-fan: fan_generic_obj.o gpio.o
- $(CC) -o bin/$@.exe obj/gpio.o obj/fan_generic_obj.o $(OFLAGS) $(CFLAGS)
+fan: fan_generic_obj.o gpio.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/gpio.o obj/fan_generic_obj.o $(LDFLAGS) $(LIBS)
-host_watchdog: host_watchdog_obj.o
- $(CC) -o bin/$@.exe obj/host_watchdog_obj.o $(OFLAGS) $(CFLAGS)
+host_watchdog: host_watchdog_obj.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/host_watchdog_obj.o $(LDFLAGS) $(LIBS)
-control_bmc: control_bmc_obj.o
- $(CC) -o bin/$@.exe obj/control_bmc_obj.o $(OFLAGS) $(CFLAGS)
+control_bmc: control_bmc_obj.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/control_bmc_obj.o $(LDFLAGS) $(LIBS)
-sensor_occ: sensor_occ_obj.o
- $(CC) -o bin/$@.exe obj/sensor_occ_obj.o $(OFLAGS) $(CFLAGS)
+sensor_occ: sensor_occ_obj.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/sensor_occ_obj.o $(LDFLAGS) $(LIBS)
-board_vpd: board_vpd_obj.o
- $(CC) -o bin/$@.exe obj/board_vpd_obj.o $(OFLAGS) $(CFLAGS)
+board_vpd: board_vpd_obj.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/board_vpd_obj.o $(LDFLAGS) $(LIBS)
-pcie_slot_present: pcie_slot_present_obj.o gpio.o
- $(CC) -o bin/$@.exe obj/pcie_slot_present_obj.o obj/gpio.o $(OFLAGS) $(CFLAGS)
+pcie_slot_present: pcie_slot_present_obj.o gpio.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/pcie_slot_present_obj.o obj/gpio.o $(LDFLAGS) $(LIBS)
-flasher: $(OBJS2) flasher_obj.o
- $(CC) -o bin/$@.exe obj/flasher_obj.o $(OFLAGS) $(OBJS3) $(CFLAGS)
+flasher: $(OBJS2) flasher_obj.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/flasher_obj.o $(OBJS3) $(LDFLAGS) $(LIBS)
-hwmon: hwmon_intf.o
- $(CC) -o bin/$@.exe obj/hwmon_intf.o $(OFLAGS) $(CFLAGS)
+hwmon: hwmon_intf.o libopenbmc_intf
+ $(CC) -o bin/$@.exe obj/hwmon_intf.o $(LDFLAGS) $(LIBS)
-all: clean setup libopenbmc_intf power_control led_controller sensor_ambient button_power control_host fan host_watchdog control_bmc board_vpd pcie_slot_present flash_bios flasher
+all: setup libopenbmc_intf power_control led_controller sensor_ambient button_power control_host fan host_watchdog control_bmc board_vpd pcie_slot_present flash_bios flasher
diff --git a/bin/ipmi_debug.py b/bin/ipmi_debug.py
index 43dbcbd..300756c 100755
--- a/bin/ipmi_debug.py
+++ b/bin/ipmi_debug.py
@@ -69,7 +69,7 @@
def main():
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
- bus = dbus.SessionBus()
+ bus = dbus.SystemBus()
name = dbus.service.BusName(DBUS_NAME, bus)
obj = IpmiDebug(bus, OBJ_NAME)
mainloop = gobject.MainLoop()
diff --git a/bin/ipmi_example.py b/bin/ipmi_example.py
index b998ba5..589c0ca 100755
--- a/bin/ipmi_example.py
+++ b/bin/ipmi_example.py
@@ -111,11 +111,14 @@
for i in status:
print i+" = "+status[i]
elif (cmd == "pokewatchdog"):
- intf = self.getWatchdog()
+ intf = getWatchdog()
intf.poke()
elif (cmd == "statewatchdog"):
- intf = self.getWatchdog()
+ intf = getWatchdog()
intf.start()
+ elif (cmd == "setwatchdog"):
+ count = int(sys.argv[2])
+ intf.set(count)
else:
print "Unsupported command"
diff --git a/bin/tftpy/COPYING b/bin/tftpy/COPYING
deleted file mode 100644
index c9f2c9c..0000000
--- a/bin/tftpy/COPYING
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License
-
-Copyright (c) 2009 Michael P. Soulier
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/bin/tftpy/README b/bin/tftpy/README
deleted file mode 100644
index ad7a871..0000000
--- a/bin/tftpy/README
+++ /dev/null
@@ -1,115 +0,0 @@
-Copyright, Michael P. Soulier, 2010.
-
-About Release 0.6.2:
-====================
-Maintenance release to fix a couple of reported issues.
-
-About Release 0.6.1:
-====================
-Maintenance release to fix several reported problems, including a rollover
-at 2^16 blocks, and some contributed work on dynamic file objects.
-
-About Release 0.6.0:
-====================
-Maintenance update to fix several reported issues, including proper
-retransmits on timeouts, and further expansion of unit tests.
-
-About Release 0.5.1:
-====================
-Maintenance update to fix a bug in the server, overhaul the documentation for
-the website, fix a typo in the unit tests, fix a failure to set default
-blocksize, and a divide by zero error in speed calculations for very short
-transfers.
-
-Also, this release adds support for input/output in client as stdin/stdout
-
-About Release 0.5.0:
-====================
-Complete rewrite of the state machine.
-Now fully implements downloading and uploading.
-
-About Release 0.4.6:
-====================
-Feature release to add the tsize option.
-Thanks to Kuba Kończyk for the patch.
-
-About Release 0.4.5:
-====================
-Bugfix release for compatability issues on Win32, among other small issues.
-
-About Release 0.4.4:
-====================
-Bugfix release for poor tolerance of unsupported options in the server.
-
-About Release 0.4.3:
-====================
-Bugfix release for an issue with the server's detection of the end of the file
-during a download.
-
-About Release 0.4.2:
-====================
-Bugfix release for some small installation issues with earlier Python
-releases.
-
-About Release 0.4.1:
-====================
-Bugfix release to fix the installation path, with some restructuring into a
-tftpy package from the single module used previously.
-
-About Release 0.4:
-==================
-This release adds a TftpServer class with a sample implementation in bin.
-The server uses a single thread with multiple handlers and a select() loop to
-handle multiple clients simultaneously.
-
-Only downloads are supported at this time.
-
-About Release 0.3:
-==================
-This release fixes a major RFC 1350 compliance problem with the remote TID.
-
-About Release 0.2:
-==================
-This release adds variable block sizes, and general option support,
-implementing RFCs 2347 and 2348. This is accessible in the TftpClient class
-via the options dict, or in the sample client via the --blocksize option.
-
-About Release 0.1:
-==================
-
-This is an initial release in the spirit of "release early, release often".
-Currently the sample client works, supporting RFC 1350. The server is not yet
-implemented, and RFC 2347 and 2348 support (variable block sizes) is underway,
-planned for 0.2.
-
-About Tftpy:
-============
-
-Purpose:
---------
-Tftpy is a TFTP library for the Python programming language. It includes
-client and server classes, with sample implementations. Hooks are included for
-easy inclusion in a UI for populating progress indicators. It supports RFCs
-1350, 2347, 2348 and the tsize option from RFC 2349.
-
-Dependencies:
--------------
-Python 2.3+, hopefully. Let me know if it fails to work.
-
-Trifles:
---------
-Home page: http://tftpy.sf.net/
-Project page: http://sourceforge.net/projects/tftpy/
-
-License is the MIT License
-
-See COPYING in this distribution.
-
-Limitations:
-------------
-- Only 'octet' mode is supported.
-- The only options supported are blksize and tsize.
-
-Author:
-=======
-Michael P. Soulier <msoulier@digitaltorque.ca>
diff --git a/bin/tftpy/TftpClient.py b/bin/tftpy/TftpClient.py
deleted file mode 100644
index 62f1dda..0000000
--- a/bin/tftpy/TftpClient.py
+++ /dev/null
@@ -1,103 +0,0 @@
-"""This module implements the TFTP Client functionality. Instantiate an
-instance of the client, and then use its upload or download method. Logging is
-performed via a standard logging object set in TftpShared."""
-
-import types
-from TftpShared import *
-from TftpPacketTypes import *
-from TftpContexts import TftpContextClientDownload, TftpContextClientUpload
-
-class TftpClient(TftpSession):
- """This class is an implementation of a tftp client. Once instantiated, a
- download can be initiated via the download() method, or an upload via the
- upload() method."""
-
- def __init__(self, host, port, options={}, localip = ""):
- TftpSession.__init__(self)
- self.context = None
- self.host = host
- self.iport = port
- self.filename = None
- self.options = options
- self.localip = localip
- if self.options.has_key('blksize'):
- size = self.options['blksize']
- tftpassert(types.IntType == type(size), "blksize must be an int")
- if size < MIN_BLKSIZE or size > MAX_BLKSIZE:
- raise TftpException, "Invalid blksize: %d" % size
-
- def download(self, filename, output, packethook=None, timeout=SOCK_TIMEOUT):
- """This method initiates a tftp download from the configured remote
- host, requesting the filename passed. It writes the file to output,
- which can be a file-like object or a path to a local file. If a
- packethook is provided, it must be a function that takes a single
- parameter, which will be a copy of each DAT packet received in the
- form of a TftpPacketDAT object. The timeout parameter may be used to
- override the default SOCK_TIMEOUT setting, which is the amount of time
- that the client will wait for a receive packet to arrive.
-
- Note: If output is a hyphen, stdout is used."""
- # We're downloading.
- log.debug("Creating download context with the following params:")
- log.debug("host = %s, port = %s, filename = %s, output = %s",
- self.host, self.iport, filename, output)
- log.debug("options = %s, packethook = %s, timeout = %s",
- self.options, packethook, timeout)
- self.context = TftpContextClientDownload(self.host,
- self.iport,
- filename,
- output,
- self.options,
- packethook,
- timeout,
- localip = self.localip)
- self.context.start()
- # Download happens here
- self.context.end()
-
- metrics = self.context.metrics
-
- log.info('')
- log.info("Download complete.")
- if metrics.duration == 0:
- log.info("Duration too short, rate undetermined")
- else:
- log.info("Downloaded %.2f bytes in %.2f seconds" % (metrics.bytes, metrics.duration))
- log.info("Average rate: %.2f kbps" % metrics.kbps)
- log.info("%.2f bytes in resent data" % metrics.resent_bytes)
- log.info("Received %d duplicate packets" % metrics.dupcount)
-
- def upload(self, filename, input, packethook=None, timeout=SOCK_TIMEOUT):
- """This method initiates a tftp upload to the configured remote host,
- uploading the filename passed. It reads the file from input, which
- can be a file-like object or a path to a local file. If a packethook
- is provided, it must be a function that takes a single parameter,
- which will be a copy of each DAT packet sent in the form of a
- TftpPacketDAT object. The timeout parameter may be used to override
- the default SOCK_TIMEOUT setting, which is the amount of time that
- the client will wait for a DAT packet to be ACKd by the server.
-
- Note: If input is a hyphen, stdin is used."""
- self.context = TftpContextClientUpload(self.host,
- self.iport,
- filename,
- input,
- self.options,
- packethook,
- timeout,
- localip = self.localip)
- self.context.start()
- # Upload happens here
- self.context.end()
-
- metrics = self.context.metrics
-
- log.info('')
- log.info("Upload complete.")
- if metrics.duration == 0:
- log.info("Duration too short, rate undetermined")
- else:
- log.info("Uploaded %d bytes in %.2f seconds" % (metrics.bytes, metrics.duration))
- log.info("Average rate: %.2f kbps" % metrics.kbps)
- log.info("%.2f bytes in resent data" % metrics.resent_bytes)
- log.info("Resent %d packets" % metrics.dupcount)
diff --git a/bin/tftpy/TftpContexts.py b/bin/tftpy/TftpContexts.py
deleted file mode 100644
index 4c41916..0000000
--- a/bin/tftpy/TftpContexts.py
+++ /dev/null
@@ -1,397 +0,0 @@
-"""This module implements all contexts for state handling during uploads and
-downloads, the main interface to which being the TftpContext base class.
-
-The concept is simple. Each context object represents a single upload or
-download, and the state object in the context object represents the current
-state of that transfer. The state object has a handle() method that expects
-the next packet in the transfer, and returns a state object until the transfer
-is complete, at which point it returns None. That is, unless there is a fatal
-error, in which case a TftpException is returned instead."""
-
-from TftpShared import *
-from TftpPacketTypes import *
-from TftpPacketFactory import TftpPacketFactory
-from TftpStates import *
-import socket, time, sys
-
-###############################################################################
-# Utility classes
-###############################################################################
-
-class TftpMetrics(object):
- """A class representing metrics of the transfer."""
- def __init__(self):
- # Bytes transferred
- self.bytes = 0
- # Bytes re-sent
- self.resent_bytes = 0
- # Duplicate packets received
- self.dups = {}
- self.dupcount = 0
- # Times
- self.start_time = 0
- self.end_time = 0
- self.duration = 0
- # Rates
- self.bps = 0
- self.kbps = 0
- # Generic errors
- self.errors = 0
-
- def compute(self):
- # Compute transfer time
- self.duration = self.end_time - self.start_time
- if self.duration == 0:
- self.duration = 1
- log.debug("TftpMetrics.compute: duration is %s", self.duration)
- self.bps = (self.bytes * 8.0) / self.duration
- self.kbps = self.bps / 1024.0
- log.debug("TftpMetrics.compute: kbps is %s", self.kbps)
- for key in self.dups:
- self.dupcount += self.dups[key]
-
- def add_dup(self, pkt):
- """This method adds a dup for a packet to the metrics."""
- log.debug("Recording a dup of %s", pkt)
- s = str(pkt)
- if self.dups.has_key(s):
- self.dups[s] += 1
- else:
- self.dups[s] = 1
- tftpassert(self.dups[s] < MAX_DUPS, "Max duplicates reached")
-
-###############################################################################
-# Context classes
-###############################################################################
-
-class TftpContext(object):
- """The base class of the contexts."""
-
- def __init__(self, host, port, timeout, localip = ""):
- """Constructor for the base context, setting shared instance
- variables."""
- self.file_to_transfer = None
- self.fileobj = None
- self.options = None
- self.packethook = None
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- if localip != "":
- self.sock.bind((localip, 0))
- self.sock.settimeout(timeout)
- self.timeout = timeout
- self.state = None
- self.next_block = 0
- self.factory = TftpPacketFactory()
- # Note, setting the host will also set self.address, as it's a property.
- self.host = host
- self.port = port
- # The port associated with the TID
- self.tidport = None
- # Metrics
- self.metrics = TftpMetrics()
- # Fluag when the transfer is pending completion.
- self.pending_complete = False
- # Time when this context last received any traffic.
- # FIXME: does this belong in metrics?
- self.last_update = 0
- # The last packet we sent, if applicable, to make resending easy.
- self.last_pkt = None
- # Count the number of retry attempts.
- self.retry_count = 0
-
- def getBlocksize(self):
- """Fetch the current blocksize for this session."""
- return int(self.options.get('blksize', 512))
-
- def __del__(self):
- """Simple destructor to try to call housekeeping in the end method if
- not called explicitely. Leaking file descriptors is not a good
- thing."""
- self.end()
-
- def checkTimeout(self, now):
- """Compare current time with last_update time, and raise an exception
- if we're over the timeout time."""
- log.debug("checking for timeout on session %s", self)
- if now - self.last_update > self.timeout:
- raise TftpTimeout, "Timeout waiting for traffic"
-
- def start(self):
- raise NotImplementedError, "Abstract method"
-
- def end(self):
- """Perform session cleanup, since the end method should always be
- called explicitely by the calling code, this works better than the
- destructor."""
- log.debug("in TftpContext.end")
- self.sock.close()
- if self.fileobj is not None and not self.fileobj.closed:
- log.debug("self.fileobj is open - closing")
- self.fileobj.close()
-
- def gethost(self):
- "Simple getter method for use in a property."
- return self.__host
-
- def sethost(self, host):
- """Setter method that also sets the address property as a result
- of the host that is set."""
- self.__host = host
- self.address = socket.gethostbyname(host)
-
- host = property(gethost, sethost)
-
- def setNextBlock(self, block):
- if block >= 2 ** 16:
- log.debug("Block number rollover to 0 again")
- block = 0
- self.__eblock = block
-
- def getNextBlock(self):
- return self.__eblock
-
- next_block = property(getNextBlock, setNextBlock)
-
- def cycle(self):
- """Here we wait for a response from the server after sending it
- something, and dispatch appropriate action to that response."""
- try:
- (buffer, (raddress, rport)) = self.sock.recvfrom(MAX_BLKSIZE)
- except socket.timeout:
- log.warn("Timeout waiting for traffic, retrying...")
- raise TftpTimeout, "Timed-out waiting for traffic"
-
- # Ok, we've received a packet. Log it.
- log.debug("Received %d bytes from %s:%s",
- len(buffer), raddress, rport)
- # And update our last updated time.
- self.last_update = time.time()
-
- # Decode it.
- recvpkt = self.factory.parse(buffer)
-
- # Check for known "connection".
- if raddress != self.address:
- log.warn("Received traffic from %s, expected host %s. Discarding"
- % (raddress, self.host))
-
- if self.tidport and self.tidport != rport:
- log.warn("Received traffic from %s:%s but we're "
- "connected to %s:%s. Discarding."
- % (raddress, rport,
- self.host, self.tidport))
-
- # If there is a packethook defined, call it. We unconditionally
- # pass all packets, it's up to the client to screen out different
- # kinds of packets. This way, the client is privy to things like
- # negotiated options.
- if self.packethook:
- self.packethook(recvpkt)
-
- # And handle it, possibly changing state.
- self.state = self.state.handle(recvpkt, raddress, rport)
- # If we didn't throw any exceptions here, reset the retry_count to
- # zero.
- self.retry_count = 0
-
-class TftpContextServer(TftpContext):
- """The context for the server."""
- def __init__(self, host, port, timeout, root, dyn_file_func=None):
- TftpContext.__init__(self,
- host,
- port,
- timeout,
- )
- # At this point we have no idea if this is a download or an upload. We
- # need to let the start state determine that.
- self.state = TftpStateServerStart(self)
-
- self.root = root
- self.dyn_file_func = dyn_file_func
-
- def __str__(self):
- return "%s:%s %s" % (self.host, self.port, self.state)
-
- def start(self, buffer):
- """Start the state cycle. Note that the server context receives an
- initial packet in its start method. Also note that the server does not
- loop on cycle(), as it expects the TftpServer object to manage
- that."""
- log.debug("In TftpContextServer.start")
- self.metrics.start_time = time.time()
- log.debug("Set metrics.start_time to %s", self.metrics.start_time)
- # And update our last updated time.
- self.last_update = time.time()
-
- pkt = self.factory.parse(buffer)
- log.debug("TftpContextServer.start() - factory returned a %s", pkt)
-
- # Call handle once with the initial packet. This should put us into
- # the download or the upload state.
- self.state = self.state.handle(pkt,
- self.host,
- self.port)
-
- def end(self):
- """Finish up the context."""
- TftpContext.end(self)
- self.metrics.end_time = time.time()
- log.debug("Set metrics.end_time to %s", self.metrics.end_time)
- self.metrics.compute()
-
-class TftpContextClientUpload(TftpContext):
- """The upload context for the client during an upload.
- Note: If input is a hyphen, then we will use stdin."""
- def __init__(self,
- host,
- port,
- filename,
- input,
- options,
- packethook,
- timeout,
- localip = ""):
- TftpContext.__init__(self,
- host,
- port,
- timeout,
- localip)
- self.file_to_transfer = filename
- self.options = options
- self.packethook = packethook
- # If the input object has a read() function,
- # assume it is file-like.
- if hasattr(input, 'read'):
- self.fileobj = input
- elif input == '-':
- self.fileobj = sys.stdin
- else:
- self.fileobj = open(input, "rb")
-
- log.debug("TftpContextClientUpload.__init__()")
- log.debug("file_to_transfer = %s, options = %s",
- self.file_to_transfer, self.options)
-
- def __str__(self):
- return "%s:%s %s" % (self.host, self.port, self.state)
-
- def start(self):
- log.info("Sending tftp upload request to %s" % self.host)
- log.info(" filename -> %s" % self.file_to_transfer)
- log.info(" options -> %s" % self.options)
-
- self.metrics.start_time = time.time()
- log.debug("Set metrics.start_time to %s", self.metrics.start_time)
-
- # FIXME: put this in a sendWRQ method?
- pkt = TftpPacketWRQ()
- pkt.filename = self.file_to_transfer
- pkt.mode = "octet" # FIXME - shouldn't hardcode this
- pkt.options = self.options
- self.sock.sendto(pkt.encode().buffer, (self.host, self.port))
- self.next_block = 1
- self.last_pkt = pkt
- # FIXME: should we centralize sendto operations so we can refactor all
- # saving of the packet to the last_pkt field?
-
- self.state = TftpStateSentWRQ(self)
-
- while self.state:
- try:
- log.debug("State is %s", self.state)
- self.cycle()
- except TftpTimeout, err:
- log.error(str(err))
- self.retry_count += 1
- if self.retry_count >= TIMEOUT_RETRIES:
- log.debug("hit max retries, giving up")
- raise
- else:
- log.warn("resending last packet")
- self.state.resendLast()
-
- def end(self):
- """Finish up the context."""
- TftpContext.end(self)
- self.metrics.end_time = time.time()
- log.debug("Set metrics.end_time to %s", self.metrics.end_time)
- self.metrics.compute()
-
-class TftpContextClientDownload(TftpContext):
- """The download context for the client during a download.
- Note: If output is a hyphen, then the output will be sent to stdout."""
- def __init__(self,
- host,
- port,
- filename,
- output,
- options,
- packethook,
- timeout,
- localip = ""):
- TftpContext.__init__(self,
- host,
- port,
- timeout,
- localip)
- # FIXME: should we refactor setting of these params?
- self.file_to_transfer = filename
- self.options = options
- self.packethook = packethook
- # If the output object has a write() function,
- # assume it is file-like.
- if hasattr(output, 'write'):
- self.fileobj = output
- # If the output filename is -, then use stdout
- elif output == '-':
- self.fileobj = sys.stdout
- else:
- self.fileobj = open(output, "wb")
-
- log.debug("TftpContextClientDownload.__init__()")
- log.debug("file_to_transfer = %s, options = %s",
- self.file_to_transfer, self.options)
-
- def __str__(self):
- return "%s:%s %s" % (self.host, self.port, self.state)
-
- def start(self):
- """Initiate the download."""
- log.info("Sending tftp download request to %s" % self.host)
- log.info(" filename -> %s" % self.file_to_transfer)
- log.info(" options -> %s" % self.options)
-
- self.metrics.start_time = time.time()
- log.debug("Set metrics.start_time to %s", self.metrics.start_time)
-
- # FIXME: put this in a sendRRQ method?
- pkt = TftpPacketRRQ()
- pkt.filename = self.file_to_transfer
- pkt.mode = "octet" # FIXME - shouldn't hardcode this
- pkt.options = self.options
- self.sock.sendto(pkt.encode().buffer, (self.host, self.port))
- self.next_block = 1
- self.last_pkt = pkt
-
- self.state = TftpStateSentRRQ(self)
-
- while self.state:
- try:
- log.debug("State is %s", self.state)
- self.cycle()
- except TftpTimeout, err:
- log.error(str(err))
- self.retry_count += 1
- if self.retry_count >= TIMEOUT_RETRIES:
- log.debug("hit max retries, giving up")
- raise
- else:
- log.warn("resending last packet")
- self.state.resendLast()
-
- def end(self):
- """Finish up the context."""
- TftpContext.end(self)
- self.metrics.end_time = time.time()
- log.debug("Set metrics.end_time to %s", self.metrics.end_time)
- self.metrics.compute()
diff --git a/bin/tftpy/TftpPacketFactory.py b/bin/tftpy/TftpPacketFactory.py
deleted file mode 100644
index 154aec8..0000000
--- a/bin/tftpy/TftpPacketFactory.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""This module implements the TftpPacketFactory class, which can take a binary
-buffer, and return the appropriate TftpPacket object to represent it, via the
-parse() method."""
-
-from TftpShared import *
-from TftpPacketTypes import *
-
-class TftpPacketFactory(object):
- """This class generates TftpPacket objects. It is responsible for parsing
- raw buffers off of the wire and returning objects representing them, via
- the parse() method."""
- def __init__(self):
- self.classes = {
- 1: TftpPacketRRQ,
- 2: TftpPacketWRQ,
- 3: TftpPacketDAT,
- 4: TftpPacketACK,
- 5: TftpPacketERR,
- 6: TftpPacketOACK
- }
-
- def parse(self, buffer):
- """This method is used to parse an existing datagram into its
- corresponding TftpPacket object. The buffer is the raw bytes off of
- the network."""
- log.debug("parsing a %d byte packet", len(buffer))
- (opcode,) = struct.unpack("!H", buffer[:2])
- log.debug("opcode is %d", opcode)
- packet = self.__create(opcode)
- packet.buffer = buffer
- return packet.decode()
-
- def __create(self, opcode):
- """This method returns the appropriate class object corresponding to
- the passed opcode."""
- tftpassert(self.classes.has_key(opcode),
- "Unsupported opcode: %d" % opcode)
-
- packet = self.classes[opcode]()
-
- return packet
diff --git a/bin/tftpy/TftpPacketTypes.py b/bin/tftpy/TftpPacketTypes.py
deleted file mode 100644
index d7c25ca..0000000
--- a/bin/tftpy/TftpPacketTypes.py
+++ /dev/null
@@ -1,445 +0,0 @@
-"""This module implements the packet types of TFTP itself, and the
-corresponding encode and decode methods for them."""
-
-import struct
-from TftpShared import *
-
-class TftpSession(object):
- """This class is the base class for the tftp client and server. Any shared
- code should be in this class."""
- # FIXME: do we need this anymore?
- pass
-
-class TftpPacketWithOptions(object):
- """This class exists to permit some TftpPacket subclasses to share code
- regarding options handling. It does not inherit from TftpPacket, as the
- goal is just to share code here, and not cause diamond inheritance."""
-
- def __init__(self):
- self.options = {}
-
- def setoptions(self, options):
- log.debug("in TftpPacketWithOptions.setoptions")
- log.debug("options: %s", str(options))
- myoptions = {}
- for key in options:
- newkey = str(key)
- myoptions[newkey] = str(options[key])
- log.debug("populated myoptions with %s = %s",
- newkey, myoptions[newkey])
-
- log.debug("setting options hash to: %s", str(myoptions))
- self._options = myoptions
-
- def getoptions(self):
- log.debug("in TftpPacketWithOptions.getoptions")
- return self._options
-
- # Set up getter and setter on options to ensure that they are the proper
- # type. They should always be strings, but we don't need to force the
- # client to necessarily enter strings if we can avoid it.
- options = property(getoptions, setoptions)
-
- def decode_options(self, buffer):
- """This method decodes the section of the buffer that contains an
- unknown number of options. It returns a dictionary of option names and
- values."""
- format = "!"
- options = {}
-
- log.debug("decode_options: buffer is: %s", repr(buffer))
- log.debug("size of buffer is %d bytes", len(buffer))
- if len(buffer) == 0:
- log.debug("size of buffer is zero, returning empty hash")
- return {}
-
- # Count the nulls in the buffer. Each one terminates a string.
- log.debug("about to iterate options buffer counting nulls")
- length = 0
- for c in buffer:
- if ord(c) == 0:
- log.debug("found a null at length %d", length)
- if length > 0:
- format += "%dsx" % length
- length = -1
- else:
- raise TftpException, "Invalid options in buffer"
- length += 1
-
- log.debug("about to unpack, format is: %s", format)
- mystruct = struct.unpack(format, buffer)
-
- tftpassert(len(mystruct) % 2 == 0,
- "packet with odd number of option/value pairs")
-
- for i in range(0, len(mystruct), 2):
- log.debug("setting option %s to %s", mystruct[i], mystruct[i+1])
- options[mystruct[i]] = mystruct[i+1]
-
- return options
-
-class TftpPacket(object):
- """This class is the parent class of all tftp packet classes. It is an
- abstract class, providing an interface, and should not be instantiated
- directly."""
- def __init__(self):
- self.opcode = 0
- self.buffer = None
-
- def encode(self):
- """The encode method of a TftpPacket takes keyword arguments specific
- to the type of packet, and packs an appropriate buffer in network-byte
- order suitable for sending over the wire.
-
- This is an abstract method."""
- raise NotImplementedError, "Abstract method"
-
- def decode(self):
- """The decode method of a TftpPacket takes a buffer off of the wire in
- network-byte order, and decodes it, populating internal properties as
- appropriate. This can only be done once the first 2-byte opcode has
- already been decoded, but the data section does include the entire
- datagram.
-
- This is an abstract method."""
- raise NotImplementedError, "Abstract method"
-
-class TftpPacketInitial(TftpPacket, TftpPacketWithOptions):
- """This class is a common parent class for the RRQ and WRQ packets, as
- they share quite a bit of code."""
- def __init__(self):
- TftpPacket.__init__(self)
- TftpPacketWithOptions.__init__(self)
- self.filename = None
- self.mode = None
-
- def encode(self):
- """Encode the packet's buffer from the instance variables."""
- tftpassert(self.filename, "filename required in initial packet")
- tftpassert(self.mode, "mode required in initial packet")
-
- ptype = None
- if self.opcode == 1: ptype = "RRQ"
- else: ptype = "WRQ"
- log.debug("Encoding %s packet, filename = %s, mode = %s",
- ptype, self.filename, self.mode)
- for key in self.options:
- log.debug(" Option %s = %s", key, self.options[key])
-
- format = "!H"
- format += "%dsx" % len(self.filename)
- if self.mode == "octet":
- format += "5sx"
- else:
- raise AssertionError, "Unsupported mode: %s" % mode
- # Add options.
- options_list = []
- if self.options.keys() > 0:
- log.debug("there are options to encode")
- for key in self.options:
- # Populate the option name
- format += "%dsx" % len(key)
- options_list.append(key)
- # Populate the option value
- format += "%dsx" % len(str(self.options[key]))
- options_list.append(str(self.options[key]))
-
- log.debug("format is %s", format)
- log.debug("options_list is %s", options_list)
- log.debug("size of struct is %d", struct.calcsize(format))
-
- self.buffer = struct.pack(format,
- self.opcode,
- self.filename,
- self.mode,
- *options_list)
-
- log.debug("buffer is %s", repr(self.buffer))
- return self
-
- def decode(self):
- tftpassert(self.buffer, "Can't decode, buffer is empty")
-
- # FIXME - this shares a lot of code with decode_options
- nulls = 0
- format = ""
- nulls = length = tlength = 0
- log.debug("in decode: about to iterate buffer counting nulls")
- subbuf = self.buffer[2:]
- for c in subbuf:
- if ord(c) == 0:
- nulls += 1
- log.debug("found a null at length %d, now have %d", length, nulls)
- format += "%dsx" % length
- length = -1
- # At 2 nulls, we want to mark that position for decoding.
- if nulls == 2:
- break
- length += 1
- tlength += 1
-
- log.debug("hopefully found end of mode at length %d", tlength)
- # length should now be the end of the mode.
- tftpassert(nulls == 2, "malformed packet")
- shortbuf = subbuf[:tlength+1]
- log.debug("about to unpack buffer with format: %s", format)
- log.debug("unpacking buffer: %s", repr(shortbuf))
- mystruct = struct.unpack(format, shortbuf)
-
- tftpassert(len(mystruct) == 2, "malformed packet")
- self.filename = mystruct[0]
- self.mode = mystruct[1].lower() # force lc - bug 17
- log.debug("set filename to %s", self.filename)
- log.debug("set mode to %s", self.mode)
-
- self.options = self.decode_options(subbuf[tlength+1:])
- return self
-
-class TftpPacketRRQ(TftpPacketInitial):
- """
-::
-
- 2 bytes string 1 byte string 1 byte
- -----------------------------------------------
- RRQ/ | 01/02 | Filename | 0 | Mode | 0 |
- WRQ -----------------------------------------------
- """
- def __init__(self):
- TftpPacketInitial.__init__(self)
- self.opcode = 1
-
- def __str__(self):
- s = 'RRQ packet: filename = %s' % self.filename
- s += ' mode = %s' % self.mode
- if self.options:
- s += '\n options = %s' % self.options
- return s
-
-class TftpPacketWRQ(TftpPacketInitial):
- """
-::
-
- 2 bytes string 1 byte string 1 byte
- -----------------------------------------------
- RRQ/ | 01/02 | Filename | 0 | Mode | 0 |
- WRQ -----------------------------------------------
- """
- def __init__(self):
- TftpPacketInitial.__init__(self)
- self.opcode = 2
-
- def __str__(self):
- s = 'WRQ packet: filename = %s' % self.filename
- s += ' mode = %s' % self.mode
- if self.options:
- s += '\n options = %s' % self.options
- return s
-
-class TftpPacketDAT(TftpPacket):
- """
-::
-
- 2 bytes 2 bytes n bytes
- ---------------------------------
- DATA | 03 | Block # | Data |
- ---------------------------------
- """
- def __init__(self):
- TftpPacket.__init__(self)
- self.opcode = 3
- self.blocknumber = 0
- self.data = None
-
- def __str__(self):
- s = 'DAT packet: block %s' % self.blocknumber
- if self.data:
- s += '\n data: %d bytes' % len(self.data)
- return s
-
- def encode(self):
- """Encode the DAT packet. This method populates self.buffer, and
- returns self for easy method chaining."""
- if len(self.data) == 0:
- log.debug("Encoding an empty DAT packet")
- format = "!HH%ds" % len(self.data)
- self.buffer = struct.pack(format,
- self.opcode,
- self.blocknumber,
- self.data)
- return self
-
- def decode(self):
- """Decode self.buffer into instance variables. It returns self for
- easy method chaining."""
- # We know the first 2 bytes are the opcode. The second two are the
- # block number.
- (self.blocknumber,) = struct.unpack("!H", self.buffer[2:4])
- log.debug("decoding DAT packet, block number %d", self.blocknumber)
- log.debug("should be %d bytes in the packet total", len(self.buffer))
- # Everything else is data.
- self.data = self.buffer[4:]
- log.debug("found %d bytes of data", len(self.data))
- return self
-
-class TftpPacketACK(TftpPacket):
- """
-::
-
- 2 bytes 2 bytes
- -------------------
- ACK | 04 | Block # |
- --------------------
- """
- def __init__(self):
- TftpPacket.__init__(self)
- self.opcode = 4
- self.blocknumber = 0
-
- def __str__(self):
- return 'ACK packet: block %d' % self.blocknumber
-
- def encode(self):
- log.debug("encoding ACK: opcode = %d, block = %d",
- self.opcode, self.blocknumber)
- self.buffer = struct.pack("!HH", self.opcode, self.blocknumber)
- return self
-
- def decode(self):
- if len(self.buffer) > 4:
- log.debug("detected TFTP ACK but request is too large, will truncate")
- log.debug("buffer was: %s", repr(self.buffer))
- self.buffer = self.buffer[0:4]
- self.opcode, self.blocknumber = struct.unpack("!HH", self.buffer)
- log.debug("decoded ACK packet: opcode = %d, block = %d",
- self.opcode, self.blocknumber)
- return self
-
-class TftpPacketERR(TftpPacket):
- """
-::
-
- 2 bytes 2 bytes string 1 byte
- ----------------------------------------
- ERROR | 05 | ErrorCode | ErrMsg | 0 |
- ----------------------------------------
-
- Error Codes
-
- Value Meaning
-
- 0 Not defined, see error message (if any).
- 1 File not found.
- 2 Access violation.
- 3 Disk full or allocation exceeded.
- 4 Illegal TFTP operation.
- 5 Unknown transfer ID.
- 6 File already exists.
- 7 No such user.
- 8 Failed to negotiate options
- """
- def __init__(self):
- TftpPacket.__init__(self)
- self.opcode = 5
- self.errorcode = 0
- # FIXME: We don't encode the errmsg...
- self.errmsg = None
- # FIXME - integrate in TftpErrors references?
- self.errmsgs = {
- 1: "File not found",
- 2: "Access violation",
- 3: "Disk full or allocation exceeded",
- 4: "Illegal TFTP operation",
- 5: "Unknown transfer ID",
- 6: "File already exists",
- 7: "No such user",
- 8: "Failed to negotiate options"
- }
-
- def __str__(self):
- s = 'ERR packet: errorcode = %d' % self.errorcode
- s += '\n msg = %s' % self.errmsgs.get(self.errorcode, '')
- return s
-
- def encode(self):
- """Encode the DAT packet based on instance variables, populating
- self.buffer, returning self."""
- format = "!HH%dsx" % len(self.errmsgs[self.errorcode])
- log.debug("encoding ERR packet with format %s", format)
- self.buffer = struct.pack(format,
- self.opcode,
- self.errorcode,
- self.errmsgs[self.errorcode])
- return self
-
- def decode(self):
- "Decode self.buffer, populating instance variables and return self."
- buflen = len(self.buffer)
- tftpassert(buflen >= 4, "malformed ERR packet, too short")
- log.debug("Decoding ERR packet, length %s bytes", buflen)
- if buflen == 4:
- log.debug("Allowing this affront to the RFC of a 4-byte packet")
- format = "!HH"
- log.debug("Decoding ERR packet with format: %s", format)
- self.opcode, self.errorcode = struct.unpack(format,
- self.buffer)
- else:
- log.debug("Good ERR packet > 4 bytes")
- format = "!HH%dsx" % (len(self.buffer) - 5)
- log.debug("Decoding ERR packet with format: %s", format)
- self.opcode, self.errorcode, self.errmsg = struct.unpack(format,
- self.buffer)
- log.error("ERR packet - errorcode: %d, message: %s"
- % (self.errorcode, self.errmsg))
- return self
-
-class TftpPacketOACK(TftpPacket, TftpPacketWithOptions):
- """
-::
-
- +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
- | opc | opt1 | 0 | value1 | 0 | optN | 0 | valueN | 0 |
- +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
- """
- def __init__(self):
- TftpPacket.__init__(self)
- TftpPacketWithOptions.__init__(self)
- self.opcode = 6
-
- def __str__(self):
- return 'OACK packet:\n options = %s' % self.options
-
- def encode(self):
- format = "!H" # opcode
- options_list = []
- log.debug("in TftpPacketOACK.encode")
- for key in self.options:
- log.debug("looping on option key %s", key)
- log.debug("value is %s", self.options[key])
- format += "%dsx" % len(key)
- format += "%dsx" % len(self.options[key])
- options_list.append(key)
- options_list.append(self.options[key])
- self.buffer = struct.pack(format, self.opcode, *options_list)
- return self
-
- def decode(self):
- self.options = self.decode_options(self.buffer[2:])
- return self
-
- def match_options(self, options):
- """This method takes a set of options, and tries to match them with
- its own. It can accept some changes in those options from the server as
- part of a negotiation. Changed or unchanged, it will return a dict of
- the options so that the session can update itself to the negotiated
- options."""
- for name in self.options:
- if options.has_key(name):
- if name == 'blksize':
- # We can accept anything between the min and max values.
- size = self.options[name]
- if size >= MIN_BLKSIZE and size <= MAX_BLKSIZE:
- log.debug("negotiated blksize of %d bytes", size)
- options[blksize] = size
- else:
- raise TftpException, "Unsupported option: %s" % name
- return True
diff --git a/bin/tftpy/TftpServer.py b/bin/tftpy/TftpServer.py
deleted file mode 100644
index 12491a0..0000000
--- a/bin/tftpy/TftpServer.py
+++ /dev/null
@@ -1,232 +0,0 @@
-"""This module implements the TFTP Server functionality. Instantiate an
-instance of the server, and then run the listen() method to listen for client
-requests. Logging is performed via a standard logging object set in
-TftpShared."""
-
-import socket, os, time
-import select
-import threading
-from TftpShared import *
-from TftpPacketTypes import *
-from TftpPacketFactory import TftpPacketFactory
-from TftpContexts import TftpContextServer
-
-class TftpServer(TftpSession):
- """This class implements a tftp server object. Run the listen() method to
- listen for client requests. It takes two optional arguments. tftproot is
- the path to the tftproot directory to serve files from and/or write them
- to. dyn_file_func is a callable that must return a file-like object to
- read from during downloads. This permits the serving of dynamic
- content."""
-
- def __init__(self, tftproot='/tftpboot', dyn_file_func=None):
- self.listenip = None
- self.listenport = None
- self.sock = None
- # FIXME: What about multiple roots?
- self.root = os.path.abspath(tftproot)
- self.dyn_file_func = dyn_file_func
- # A dict of sessions, where each session is keyed by a string like
- # ip:tid for the remote end.
- self.sessions = {}
- # A threading event to help threads synchronize with the server
- # is_running state.
- self.is_running = threading.Event()
-
- self.shutdown_gracefully = False
- self.shutdown_immediately = False
-
- if self.dyn_file_func:
- if not callable(self.dyn_file_func):
- raise TftpException, "A dyn_file_func supplied, but it is not callable."
- elif os.path.exists(self.root):
- log.debug("tftproot %s does exist", self.root)
- if not os.path.isdir(self.root):
- raise TftpException, "The tftproot must be a directory."
- else:
- log.debug("tftproot %s is a directory", self.root)
- if os.access(self.root, os.R_OK):
- log.debug("tftproot %s is readable", self.root)
- else:
- raise TftpException, "The tftproot must be readable"
- if os.access(self.root, os.W_OK):
- log.debug("tftproot %s is writable", self.root)
- else:
- log.warning("The tftproot %s is not writable" % self.root)
- else:
- raise TftpException, "The tftproot does not exist."
-
- def listen(self,
- listenip="",
- listenport=DEF_TFTP_PORT,
- timeout=SOCK_TIMEOUT):
- """Start a server listening on the supplied interface and port. This
- defaults to INADDR_ANY (all interfaces) and UDP port 69. You can also
- supply a different socket timeout value, if desired."""
- tftp_factory = TftpPacketFactory()
-
- # Don't use new 2.5 ternary operator yet
- # listenip = listenip if listenip else '0.0.0.0'
- if not listenip: listenip = '0.0.0.0'
- log.info("Server requested on ip %s, port %s"
- % (listenip, listenport))
- try:
- # FIXME - sockets should be non-blocking
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- self.sock.bind((listenip, listenport))
- _, self.listenport = self.sock.getsockname()
- except socket.error, err:
- # Reraise it for now.
- raise
-
- self.is_running.set()
-
- log.info("Starting receive loop...")
- while True:
- log.debug("shutdown_immediately is %s", self.shutdown_immediately)
- log.debug("shutdown_gracefully is %s", self.shutdown_gracefully)
- if self.shutdown_immediately:
- log.warn("Shutting down now. Session count: %d" % len(self.sessions))
- self.sock.close()
- for key in self.sessions:
- self.sessions[key].end()
- self.sessions = []
- break
-
- elif self.shutdown_gracefully:
- if not self.sessions:
- log.warn("In graceful shutdown mode and all sessions complete.")
- self.sock.close()
- break
-
- # Build the inputlist array of sockets to select() on.
- inputlist = []
- inputlist.append(self.sock)
- for key in self.sessions:
- inputlist.append(self.sessions[key].sock)
-
- # Block until some socket has input on it.
- log.debug("Performing select on this inputlist: %s", inputlist)
- readyinput, readyoutput, readyspecial = select.select(inputlist,
- [],
- [],
- SOCK_TIMEOUT)
-
- deletion_list = []
-
- # Handle the available data, if any. Maybe we timed-out.
- for readysock in readyinput:
- # Is the traffic on the main server socket? ie. new session?
- if readysock == self.sock:
- log.debug("Data ready on our main socket")
- buffer, (raddress, rport) = self.sock.recvfrom(MAX_BLKSIZE)
-
- log.debug("Read %d bytes", len(buffer))
-
- if self.shutdown_gracefully:
- log.warn("Discarding data on main port, in graceful shutdown mode")
- continue
-
- # Forge a session key based on the client's IP and port,
- # which should safely work through NAT.
- key = "%s:%s" % (raddress, rport)
-
- if not self.sessions.has_key(key):
- log.debug("Creating new server context for "
- "session key = %s", key)
- self.sessions[key] = TftpContextServer(raddress,
- rport,
- timeout,
- self.root,
- self.dyn_file_func)
- try:
- self.sessions[key].start(buffer)
- except TftpException, err:
- deletion_list.append(key)
- log.error("Fatal exception thrown from "
- "session %s: %s" % (key, str(err)))
- else:
- log.warn("received traffic on main socket for "
- "existing session??")
- log.info("Currently handling these sessions:")
- for session_key, session in self.sessions.items():
- log.info(" %s" % session)
-
- else:
- # Must find the owner of this traffic.
- for key in self.sessions:
- if readysock == self.sessions[key].sock:
- log.info("Matched input to session key %s"
- % key)
- try:
- self.sessions[key].cycle()
- if self.sessions[key].state == None:
- log.info("Successful transfer.")
- deletion_list.append(key)
- except TftpException, err:
- deletion_list.append(key)
- log.error("Fatal exception thrown from "
- "session %s: %s"
- % (key, str(err)))
- # Break out of for loop since we found the correct
- # session.
- break
-
- else:
- log.error("Can't find the owner for this packet. "
- "Discarding.")
-
- log.debug("Looping on all sessions to check for timeouts")
- now = time.time()
- for key in self.sessions:
- try:
- self.sessions[key].checkTimeout(now)
- except TftpTimeout, err:
- log.error(str(err))
- self.sessions[key].retry_count += 1
- if self.sessions[key].retry_count >= TIMEOUT_RETRIES:
- log.debug("hit max retries on %s, giving up",
- self.sessions[key])
- deletion_list.append(key)
- else:
- log.debug("resending on session %s", self.sessions[key])
- self.sessions[key].state.resendLast()
-
- log.debug("Iterating deletion list.")
- for key in deletion_list:
- log.info('')
- log.info("Session %s complete" % key)
- if self.sessions.has_key(key):
- log.debug("Gathering up metrics from session before deleting")
- self.sessions[key].end()
- metrics = self.sessions[key].metrics
- if metrics.duration == 0:
- log.info("Duration too short, rate undetermined")
- else:
- log.info("Transferred %d bytes in %.2f seconds"
- % (metrics.bytes, metrics.duration))
- log.info("Average rate: %.2f kbps" % metrics.kbps)
- log.info("%.2f bytes in resent data" % metrics.resent_bytes)
- log.info("%d duplicate packets" % metrics.dupcount)
- log.debug("Deleting session %s", key)
- del self.sessions[key]
- log.debug("Session list is now %s", self.sessions)
- else:
- log.warn("Strange, session %s is not on the deletion list"
- % key)
-
- self.is_running.clear()
-
- log.debug("server returning from while loop")
- self.shutdown_gracefully = self.shutdown_immediately = False
-
- def stop(self, now=False):
- """Stop the server gracefully. Do not take any new transfers,
- but complete the existing ones. If force is True, drop everything
- and stop. Note, immediately will not interrupt the select loop, it
- will happen when the server returns on ready data, or a timeout.
- ie. SOCK_TIMEOUT"""
- if now:
- self.shutdown_immediately = True
- else:
- self.shutdown_gracefully = True
diff --git a/bin/tftpy/TftpShared.py b/bin/tftpy/TftpShared.py
deleted file mode 100644
index d09d8bd..0000000
--- a/bin/tftpy/TftpShared.py
+++ /dev/null
@@ -1,59 +0,0 @@
-"""This module holds all objects shared by all other modules in tftpy."""
-
-import logging
-
-LOG_LEVEL = logging.NOTSET
-MIN_BLKSIZE = 8
-DEF_BLKSIZE = 512
-MAX_BLKSIZE = 65536
-SOCK_TIMEOUT = 5
-MAX_DUPS = 20
-TIMEOUT_RETRIES = 5
-DEF_TFTP_PORT = 69
-
-# A hook for deliberately introducing delay in testing.
-DELAY_BLOCK = 0
-
-# Initialize the logger.
-logging.basicConfig()
-# The logger used by this library. Feel free to clobber it with your own, if you like, as
-# long as it conforms to Python's logging.
-log = logging.getLogger('tftpy')
-
-def tftpassert(condition, msg):
- """This function is a simple utility that will check the condition
- passed for a false state. If it finds one, it throws a TftpException
- with the message passed. This just makes the code throughout cleaner
- by refactoring."""
- if not condition:
- raise TftpException, msg
-
-def setLogLevel(level):
- """This function is a utility function for setting the internal log level.
- The log level defaults to logging.NOTSET, so unwanted output to stdout is
- not created."""
- global log
- log.setLevel(level)
-
-class TftpErrors(object):
- """This class is a convenience for defining the common tftp error codes,
- and making them more readable in the code."""
- NotDefined = 0
- FileNotFound = 1
- AccessViolation = 2
- DiskFull = 3
- IllegalTftpOp = 4
- UnknownTID = 5
- FileAlreadyExists = 6
- NoSuchUser = 7
- FailedNegotiation = 8
-
-class TftpException(Exception):
- """This class is the parent class of all exceptions regarding the handling
- of the TFTP protocol."""
- pass
-
-class TftpTimeout(TftpException):
- """This class represents a timeout error waiting for a response from the
- other end."""
- pass
diff --git a/bin/tftpy/TftpStates.py b/bin/tftpy/TftpStates.py
deleted file mode 100644
index 1ea6c31..0000000
--- a/bin/tftpy/TftpStates.py
+++ /dev/null
@@ -1,582 +0,0 @@
-"""This module implements all state handling during uploads and downloads, the
-main interface to which being the TftpState base class.
-
-The concept is simple. Each context object represents a single upload or
-download, and the state object in the context object represents the current
-state of that transfer. The state object has a handle() method that expects
-the next packet in the transfer, and returns a state object until the transfer
-is complete, at which point it returns None. That is, unless there is a fatal
-error, in which case a TftpException is returned instead."""
-
-from TftpShared import *
-from TftpPacketTypes import *
-import os
-
-###############################################################################
-# State classes
-###############################################################################
-
-class TftpState(object):
- """The base class for the states."""
-
- def __init__(self, context):
- """Constructor for setting up common instance variables. The involved
- file object is required, since in tftp there's always a file
- involved."""
- self.context = context
-
- def handle(self, pkt, raddress, rport):
- """An abstract method for handling a packet. It is expected to return
- a TftpState object, either itself or a new state."""
- raise NotImplementedError, "Abstract method"
-
- def handleOACK(self, pkt):
- """This method handles an OACK from the server, syncing any accepted
- options."""
- if pkt.options.keys() > 0:
- if pkt.match_options(self.context.options):
- log.info("Successful negotiation of options")
- # Set options to OACK options
- self.context.options = pkt.options
- for key in self.context.options:
- log.info(" %s = %s" % (key, self.context.options[key]))
- else:
- log.error("Failed to negotiate options")
- raise TftpException, "Failed to negotiate options"
- else:
- raise TftpException, "No options found in OACK"
-
- def returnSupportedOptions(self, options):
- """This method takes a requested options list from a client, and
- returns the ones that are supported."""
- # We support the options blksize and tsize right now.
- # FIXME - put this somewhere else?
- accepted_options = {}
- for option in options:
- if option == 'blksize':
- # Make sure it's valid.
- if int(options[option]) > MAX_BLKSIZE:
- log.info("Client requested blksize greater than %d "
- "setting to maximum" % MAX_BLKSIZE)
- accepted_options[option] = MAX_BLKSIZE
- elif int(options[option]) < MIN_BLKSIZE:
- log.info("Client requested blksize less than %d "
- "setting to minimum" % MIN_BLKSIZE)
- accepted_options[option] = MIN_BLKSIZE
- else:
- accepted_options[option] = options[option]
- elif option == 'tsize':
- log.debug("tsize option is set")
- accepted_options['tsize'] = 1
- else:
- log.info("Dropping unsupported option '%s'" % option)
- log.debug("Returning these accepted options: %s", accepted_options)
- return accepted_options
-
- def sendDAT(self):
- """This method sends the next DAT packet based on the data in the
- context. It returns a boolean indicating whether the transfer is
- finished."""
- finished = False
- blocknumber = self.context.next_block
- # Test hook
- if DELAY_BLOCK and DELAY_BLOCK == blocknumber:
- import time
- log.debug("Deliberately delaying 10 seconds...")
- time.sleep(10)
- dat = None
- blksize = self.context.getBlocksize()
- buffer = self.context.fileobj.read(blksize)
- log.debug("Read %d bytes into buffer", len(buffer))
- if len(buffer) < blksize:
- log.info("Reached EOF on file %s"
- % self.context.file_to_transfer)
- finished = True
- dat = TftpPacketDAT()
- dat.data = buffer
- dat.blocknumber = blocknumber
- self.context.metrics.bytes += len(dat.data)
- log.debug("Sending DAT packet %d", dat.blocknumber)
- self.context.sock.sendto(dat.encode().buffer,
- (self.context.host, self.context.tidport))
- if self.context.packethook:
- self.context.packethook(dat)
- self.context.last_pkt = dat
- return finished
-
- def sendACK(self, blocknumber=None):
- """This method sends an ack packet to the block number specified. If
- none is specified, it defaults to the next_block property in the
- parent context."""
- log.debug("In sendACK, passed blocknumber is %s", blocknumber)
- if blocknumber is None:
- blocknumber = self.context.next_block
- log.info("Sending ack to block %d" % blocknumber)
- ackpkt = TftpPacketACK()
- ackpkt.blocknumber = blocknumber
- self.context.sock.sendto(ackpkt.encode().buffer,
- (self.context.host,
- self.context.tidport))
- self.context.last_pkt = ackpkt
-
- def sendError(self, errorcode):
- """This method uses the socket passed, and uses the errorcode to
- compose and send an error packet."""
- log.debug("In sendError, being asked to send error %d", errorcode)
- errpkt = TftpPacketERR()
- errpkt.errorcode = errorcode
- self.context.sock.sendto(errpkt.encode().buffer,
- (self.context.host,
- self.context.tidport))
- self.context.last_pkt = errpkt
-
- def sendOACK(self):
- """This method sends an OACK packet with the options from the current
- context."""
- log.debug("In sendOACK with options %s", self.context.options)
- pkt = TftpPacketOACK()
- pkt.options = self.context.options
- self.context.sock.sendto(pkt.encode().buffer,
- (self.context.host,
- self.context.tidport))
- self.context.last_pkt = pkt
-
- def resendLast(self):
- "Resend the last sent packet due to a timeout."
- log.warn("Resending packet %s on sessions %s"
- % (self.context.last_pkt, self))
- self.context.metrics.resent_bytes += len(self.context.last_pkt.buffer)
- self.context.metrics.add_dup(self.context.last_pkt)
- sendto_port = self.context.tidport
- if not sendto_port:
- # If the tidport wasn't set, then the remote end hasn't even
- # started talking to us yet. That's not good. Maybe it's not
- # there.
- sendto_port = self.context.port
- self.context.sock.sendto(self.context.last_pkt.encode().buffer,
- (self.context.host, sendto_port))
- if self.context.packethook:
- self.context.packethook(self.context.last_pkt)
-
- def handleDat(self, pkt):
- """This method handles a DAT packet during a client download, or a
- server upload."""
- log.info("Handling DAT packet - block %d" % pkt.blocknumber)
- log.debug("Expecting block %s", self.context.next_block)
- if pkt.blocknumber == self.context.next_block:
- log.debug("Good, received block %d in sequence", pkt.blocknumber)
-
- self.sendACK()
- self.context.next_block += 1
-
- log.debug("Writing %d bytes to output file", len(pkt.data))
- self.context.fileobj.write(pkt.data)
- self.context.metrics.bytes += len(pkt.data)
- # Check for end-of-file, any less than full data packet.
- if len(pkt.data) < self.context.getBlocksize():
- log.info("End of file detected")
- return None
-
- elif pkt.blocknumber < self.context.next_block:
- if pkt.blocknumber == 0:
- log.warn("There is no block zero!")
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "There is no block zero!"
- log.warn("Dropping duplicate block %d" % pkt.blocknumber)
- self.context.metrics.add_dup(pkt)
- log.debug("ACKing block %d again, just in case", pkt.blocknumber)
- self.sendACK(pkt.blocknumber)
-
- else:
- # FIXME: should we be more tolerant and just discard instead?
- msg = "Whoa! Received future block %d but expected %d" \
- % (pkt.blocknumber, self.context.next_block)
- log.error(msg)
- raise TftpException, msg
-
- # Default is to ack
- return TftpStateExpectDAT(self.context)
-
-class TftpServerState(TftpState):
- """The base class for server states."""
-
- def __init__(self, context):
- TftpState.__init__(self, context)
-
- # This variable is used to store the absolute path to the file being
- # managed.
- self.full_path = None
-
- def serverInitial(self, pkt, raddress, rport):
- """This method performs initial setup for a server context transfer,
- put here to refactor code out of the TftpStateServerRecvRRQ and
- TftpStateServerRecvWRQ classes, since their initial setup is
- identical. The method returns a boolean, sendoack, to indicate whether
- it is required to send an OACK to the client."""
- options = pkt.options
- sendoack = False
- if not self.context.tidport:
- self.context.tidport = rport
- log.info("Setting tidport to %s" % rport)
-
- log.debug("Setting default options, blksize")
- self.context.options = { 'blksize': DEF_BLKSIZE }
-
- if options:
- log.debug("Options requested: %s", options)
- supported_options = self.returnSupportedOptions(options)
- self.context.options.update(supported_options)
- sendoack = True
-
- # FIXME - only octet mode is supported at this time.
- if pkt.mode != 'octet':
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, \
- "Only octet transfers are supported at this time."
-
- # test host/port of client end
- if self.context.host != raddress or self.context.port != rport:
- self.sendError(TftpErrors.UnknownTID)
- log.error("Expected traffic from %s:%s but received it "
- "from %s:%s instead."
- % (self.context.host,
- self.context.port,
- raddress,
- rport))
- # FIXME: increment an error count?
- # Return same state, we're still waiting for valid traffic.
- return self
-
- log.debug("Requested filename is %s", pkt.filename)
-
- # Build the filename on this server and ensure it is contained
- # in the specified root directory.
- #
- # Filenames that begin with server root are accepted. It's
- # assumed the client and server are tightly connected and this
- # provides backwards compatibility.
- #
- # Filenames otherwise are relative to the server root. If they
- # begin with a '/' strip it off as otherwise os.path.join will
- # treat it as absolute (regardless of whether it is ntpath or
- # posixpath module
- if pkt.filename.startswith(self.context.root):
- full_path = pkt.filename
- else:
- full_path = os.path.join(
- self.context.root, pkt.filename.lstrip('/'))
-
- # Use abspath to eliminate any remaining relative elements
- # (e.g. '..') and ensure that is still within the server's
- # root directory
- self.full_path = os.path.abspath(full_path)
- log.debug("full_path is %s", full_path)
- if self.full_path.startswith(self.context.root):
- log.info("requested file is in the server root - good")
- else:
- log.warn("requested file is not within the server root - bad")
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "bad file path"
-
- self.context.file_to_transfer = pkt.filename
-
- return sendoack
-
-
-class TftpStateServerRecvRRQ(TftpServerState):
- """This class represents the state of the TFTP server when it has just
- received an RRQ packet."""
- def handle(self, pkt, raddress, rport):
- "Handle an initial RRQ packet as a server."
- log.debug("In TftpStateServerRecvRRQ.handle")
- sendoack = self.serverInitial(pkt, raddress, rport)
- path = self.full_path
- log.info("Opening file %s for reading" % path)
- if os.path.exists(path):
- # Note: Open in binary mode for win32 portability, since win32
- # blows.
- self.context.fileobj = open(path, "rb")
- elif self.context.dyn_file_func:
- log.debug("No such file %s but using dyn_file_func", path)
- self.context.fileobj = \
- self.context.dyn_file_func(self.context.file_to_transfer)
-
- if self.context.fileobj is None:
- log.debug("dyn_file_func returned 'None', treating as "
- "FileNotFound")
- self.sendError(TftpErrors.FileNotFound)
- raise TftpException, "File not found: %s" % path
- else:
- self.sendError(TftpErrors.FileNotFound)
- raise TftpException, "File not found: %s" % path
-
- # Options negotiation.
- if sendoack:
- # Note, next_block is 0 here since that's the proper
- # acknowledgement to an OACK.
- # FIXME: perhaps we do need a TftpStateExpectOACK class...
- self.sendOACK()
- # Note, self.context.next_block is already 0.
- else:
- self.context.next_block = 1
- log.debug("No requested options, starting send...")
- self.context.pending_complete = self.sendDAT()
- # Note, we expect an ack regardless of whether we sent a DAT or an
- # OACK.
- return TftpStateExpectACK(self.context)
-
- # Note, we don't have to check any other states in this method, that's
- # up to the caller.
-
-class TftpStateServerRecvWRQ(TftpServerState):
- """This class represents the state of the TFTP server when it has just
- received a WRQ packet."""
- def make_subdirs(self):
- """The purpose of this method is to, if necessary, create all of the
- subdirectories leading up to the file to the written."""
- # Pull off everything below the root.
- subpath = self.full_path[len(self.context.root):]
- log.debug("make_subdirs: subpath is %s", subpath)
- # Split on directory separators, but drop the last one, as it should
- # be the filename.
- dirs = subpath.split(os.sep)[:-1]
- log.debug("dirs is %s", dirs)
- current = self.context.root
- for dir in dirs:
- if dir:
- current = os.path.join(current, dir)
- if os.path.isdir(current):
- log.debug("%s is already an existing directory", current)
- else:
- os.mkdir(current, 0700)
-
- def handle(self, pkt, raddress, rport):
- "Handle an initial WRQ packet as a server."
- log.debug("In TftpStateServerRecvWRQ.handle")
- sendoack = self.serverInitial(pkt, raddress, rport)
- path = self.full_path
- log.info("Opening file %s for writing" % path)
- if os.path.exists(path):
- # FIXME: correct behavior?
- log.warn("File %s exists already, overwriting..." % self.context.file_to_transfer)
- # FIXME: I think we should upload to a temp file and not overwrite the
- # existing file until the file is successfully uploaded.
- self.make_subdirs()
- self.context.fileobj = open(path, "wb")
-
- # Options negotiation.
- if sendoack:
- log.debug("Sending OACK to client")
- self.sendOACK()
- else:
- log.debug("No requested options, expecting transfer to begin...")
- self.sendACK()
- # Whether we're sending an oack or not, we're expecting a DAT for
- # block 1
- self.context.next_block = 1
- # We may have sent an OACK, but we're expecting a DAT as the response
- # to either the OACK or an ACK, so lets unconditionally use the
- # TftpStateExpectDAT state.
- return TftpStateExpectDAT(self.context)
-
- # Note, we don't have to check any other states in this method, that's
- # up to the caller.
-
-class TftpStateServerStart(TftpState):
- """The start state for the server. This is a transitory state since at
- this point we don't know if we're handling an upload or a download. We
- will commit to one of them once we interpret the initial packet."""
- def handle(self, pkt, raddress, rport):
- """Handle a packet we just received."""
- log.debug("In TftpStateServerStart.handle")
- if isinstance(pkt, TftpPacketRRQ):
- log.debug("Handling an RRQ packet")
- return TftpStateServerRecvRRQ(self.context).handle(pkt,
- raddress,
- rport)
- elif isinstance(pkt, TftpPacketWRQ):
- log.debug("Handling a WRQ packet")
- return TftpStateServerRecvWRQ(self.context).handle(pkt,
- raddress,
- rport)
- else:
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, \
- "Invalid packet to begin up/download: %s" % pkt
-
-class TftpStateExpectACK(TftpState):
- """This class represents the state of the transfer when a DAT was just
- sent, and we are waiting for an ACK from the server. This class is the
- same one used by the client during the upload, and the server during the
- download."""
- def handle(self, pkt, raddress, rport):
- "Handle a packet, hopefully an ACK since we just sent a DAT."
- if isinstance(pkt, TftpPacketACK):
- log.info("Received ACK for packet %d" % pkt.blocknumber)
- # Is this an ack to the one we just sent?
- if self.context.next_block == pkt.blocknumber:
- if self.context.pending_complete:
- log.info("Received ACK to final DAT, we're done.")
- return None
- else:
- log.debug("Good ACK, sending next DAT")
- self.context.next_block += 1
- log.debug("Incremented next_block to %d",
- self.context.next_block)
- self.context.pending_complete = self.sendDAT()
-
- elif pkt.blocknumber < self.context.next_block:
- log.warn("Received duplicate ACK for block %d"
- % pkt.blocknumber)
- self.context.metrics.add_dup(pkt)
-
- else:
- log.warn("Oooh, time warp. Received ACK to packet we "
- "didn't send yet. Discarding.")
- self.context.metrics.errors += 1
- return self
- elif isinstance(pkt, TftpPacketERR):
- log.error("Received ERR packet from peer: %s" % str(pkt))
- raise TftpException, \
- "Received ERR packet from peer: %s" % str(pkt)
- else:
- log.warn("Discarding unsupported packet: %s" % str(pkt))
- return self
-
-class TftpStateExpectDAT(TftpState):
- """Just sent an ACK packet. Waiting for DAT."""
- def handle(self, pkt, raddress, rport):
- """Handle the packet in response to an ACK, which should be a DAT."""
- if isinstance(pkt, TftpPacketDAT):
- return self.handleDat(pkt)
-
- # Every other packet type is a problem.
- elif isinstance(pkt, TftpPacketACK):
- # Umm, we ACK, you don't.
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received ACK from peer when expecting DAT"
-
- elif isinstance(pkt, TftpPacketWRQ):
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received WRQ from peer when expecting DAT"
-
- elif isinstance(pkt, TftpPacketERR):
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received ERR from peer: " + str(pkt)
-
- else:
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received unknown packet type from peer: " + str(pkt)
-
-class TftpStateSentWRQ(TftpState):
- """Just sent an WRQ packet for an upload."""
- def handle(self, pkt, raddress, rport):
- """Handle a packet we just received."""
- if not self.context.tidport:
- self.context.tidport = rport
- log.debug("Set remote port for session to %s", rport)
-
- # If we're going to successfully transfer the file, then we should see
- # either an OACK for accepted options, or an ACK to ignore options.
- if isinstance(pkt, TftpPacketOACK):
- log.info("Received OACK from server")
- try:
- self.handleOACK(pkt)
- except TftpException:
- log.error("Failed to negotiate options")
- self.sendError(TftpErrors.FailedNegotiation)
- raise
- else:
- log.debug("Sending first DAT packet")
- self.context.pending_complete = self.sendDAT()
- log.debug("Changing state to TftpStateExpectACK")
- return TftpStateExpectACK(self.context)
-
- elif isinstance(pkt, TftpPacketACK):
- log.info("Received ACK from server")
- log.debug("Apparently the server ignored our options")
- # The block number should be zero.
- if pkt.blocknumber == 0:
- log.debug("Ack blocknumber is zero as expected")
- log.debug("Sending first DAT packet")
- self.context.pending_complete = self.sendDAT()
- log.debug("Changing state to TftpStateExpectACK")
- return TftpStateExpectACK(self.context)
- else:
- log.warn("Discarding ACK to block %s" % pkt.blocknumber)
- log.debug("Still waiting for valid response from server")
- return self
-
- elif isinstance(pkt, TftpPacketERR):
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received ERR from server: " + str(pkt)
-
- elif isinstance(pkt, TftpPacketRRQ):
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received RRQ from server while in upload"
-
- elif isinstance(pkt, TftpPacketDAT):
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received DAT from server while in upload"
-
- else:
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received unknown packet type from server: " + str(pkt)
-
- # By default, no state change.
- return self
-
-class TftpStateSentRRQ(TftpState):
- """Just sent an RRQ packet."""
- def handle(self, pkt, raddress, rport):
- """Handle the packet in response to an RRQ to the server."""
- if not self.context.tidport:
- self.context.tidport = rport
- log.info("Set remote port for session to %s" % rport)
-
- # Now check the packet type and dispatch it properly.
- if isinstance(pkt, TftpPacketOACK):
- log.info("Received OACK from server")
- try:
- self.handleOACK(pkt)
- except TftpException, err:
- log.error("Failed to negotiate options: %s" % str(err))
- self.sendError(TftpErrors.FailedNegotiation)
- raise
- else:
- log.debug("Sending ACK to OACK")
-
- self.sendACK(blocknumber=0)
-
- log.debug("Changing state to TftpStateExpectDAT")
- return TftpStateExpectDAT(self.context)
-
- elif isinstance(pkt, TftpPacketDAT):
- # If there are any options set, then the server didn't honour any
- # of them.
- log.info("Received DAT from server")
- if self.context.options:
- log.info("Server ignored options, falling back to defaults")
- self.context.options = { 'blksize': DEF_BLKSIZE }
- return self.handleDat(pkt)
-
- # Every other packet type is a problem.
- elif isinstance(pkt, TftpPacketACK):
- # Umm, we ACK, the server doesn't.
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received ACK from server while in download"
-
- elif isinstance(pkt, TftpPacketWRQ):
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received WRQ from server while in download"
-
- elif isinstance(pkt, TftpPacketERR):
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received ERR from server: " + str(pkt)
-
- else:
- self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received unknown packet type from server: " + str(pkt)
-
- # By default, no state change.
- return self
diff --git a/bin/tftpy/__init__.py b/bin/tftpy/__init__.py
deleted file mode 100644
index fba9a9f..0000000
--- a/bin/tftpy/__init__.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""
-This library implements the tftp protocol, based on rfc 1350.
-http://www.faqs.org/rfcs/rfc1350.html
-At the moment it implements only a client class, but will include a server,
-with support for variable block sizes.
-
-As a client of tftpy, this is the only module that you should need to import
-directly. The TftpClient and TftpServer classes can be reached through it.
-"""
-
-import sys
-
-# Make sure that this is at least Python 2.3
-required_version = (2, 3)
-if sys.version_info < required_version:
- raise ImportError, "Requires at least Python 2.3"
-
-from tftpy.TftpShared import *
-from tftpy.TftpPacketTypes import *
-from tftpy.TftpPacketFactory import *
-from tftpy.TftpClient import *
-from tftpy.TftpServer import *
-from tftpy.TftpContexts import *
-from tftpy.TftpStates import *
-
diff --git a/interfaces/openbmc_intf.c b/interfaces/openbmc_intf.c
index 81ed6ea..cf60578 100644
--- a/interfaces/openbmc_intf.c
+++ b/interfaces/openbmc_intf.c
@@ -1,5 +1,5 @@
/*
- * Generated by gdbus-codegen 2.40.2. DO NOT EDIT.
+ * Generated by gdbus-codegen 2.44.1. DO NOT EDIT.
*
* The license of this code is the same as for the source it was derived from.
*/
@@ -149,6 +149,1539 @@
}
/* ------------------------------------------------------------------------
+<<<<<<< HEAD
+ * Code for interface org.openbmc.Occ
+ * ------------------------------------------------------------------------
+ */
+
+/**
+ * SECTION:Occ
+ * @title: Occ
+ * @short_description: Generated C code for the org.openbmc.Occ D-Bus interface
+ *
+ * This section contains code for working with the <link linkend="gdbus-interface-org-openbmc-Occ.top_of_page">org.openbmc.Occ</link> D-Bus interface in C.
+ */
+
+/* ---- Introspection data for org.openbmc.Occ ---- */
+
+static const _ExtendedGDBusMethodInfo _occ_method_info_init =
+{
+ {
+ -1,
+ (gchar *) "init",
+ NULL,
+ NULL,
+ NULL
+ },
+ "handle-init",
+ FALSE
+};
+
+static const _ExtendedGDBusMethodInfo _occ_method_info_collect =
+{
+ {
+ -1,
+ (gchar *) "collect",
+ NULL,
+ NULL,
+ NULL
+ },
+ "handle-collect",
+ FALSE
+};
+
+static const _ExtendedGDBusMethodInfo * const _occ_method_info_pointers[] =
+{
+ &_occ_method_info_init,
+ &_occ_method_info_collect,
+ NULL
+};
+
+static const _ExtendedGDBusPropertyInfo _occ_property_info_state =
+{
+ {
+ -1,
+ (gchar *) "state",
+ (gchar *) "s",
+ G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE,
+ NULL
+ },
+ "state",
+ FALSE
+};
+
+static const _ExtendedGDBusPropertyInfo _occ_property_info_instance_name =
+{
+ {
+ -1,
+ (gchar *) "instance_name",
+ (gchar *) "s",
+ G_DBUS_PROPERTY_INFO_FLAGS_READABLE,
+ NULL
+ },
+ "instance-name",
+ FALSE
+};
+
+static const _ExtendedGDBusPropertyInfo _occ_property_info_poll_interval =
+{
+ {
+ -1,
+ (gchar *) "poll_interval",
+ (gchar *) "i",
+ G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE,
+ NULL
+ },
+ "poll-interval",
+ FALSE
+};
+
+static const _ExtendedGDBusPropertyInfo * const _occ_property_info_pointers[] =
+{
+ &_occ_property_info_state,
+ &_occ_property_info_instance_name,
+ &_occ_property_info_poll_interval,
+ NULL
+};
+
+static const _ExtendedGDBusInterfaceInfo _occ_interface_info =
+{
+ {
+ -1,
+ (gchar *) "org.openbmc.Occ",
+ (GDBusMethodInfo **) &_occ_method_info_pointers,
+ NULL,
+ (GDBusPropertyInfo **) &_occ_property_info_pointers,
+ NULL
+ },
+ "occ",
+};
+
+
+/**
+ * occ_interface_info:
+ *
+ * Gets a machine-readable description of the <link linkend="gdbus-interface-org-openbmc-Occ.top_of_page">org.openbmc.Occ</link> D-Bus interface.
+ *
+ * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free.
+ */
+GDBusInterfaceInfo *
+occ_interface_info (void)
+{
+ return (GDBusInterfaceInfo *) &_occ_interface_info.parent_struct;
+}
+
+/**
+ * occ_override_properties:
+ * @klass: The class structure for a #GObject<!-- -->-derived class.
+ * @property_id_begin: The property id to assign to the first overridden property.
+ *
+ * Overrides all #GObject properties in the #Occ interface for a concrete class.
+ * The properties are overridden in the order they are defined.
+ *
+ * Returns: The last property id.
+ */
+guint
+occ_override_properties (GObjectClass *klass, guint property_id_begin)
+{
+ g_object_class_override_property (klass, property_id_begin++, "state");
+ g_object_class_override_property (klass, property_id_begin++, "instance-name");
+ g_object_class_override_property (klass, property_id_begin++, "poll-interval");
+ return property_id_begin - 1;
+}
+
+
+
+/**
+ * Occ:
+ *
+ * Abstract interface type for the D-Bus interface <link linkend="gdbus-interface-org-openbmc-Occ.top_of_page">org.openbmc.Occ</link>.
+ */
+
+/**
+ * OccIface:
+ * @parent_iface: The parent interface.
+ * @handle_collect: Handler for the #Occ::handle-collect signal.
+ * @handle_init: Handler for the #Occ::handle-init signal.
+ * @get_instance_name: Getter for the #Occ:instance-name property.
+ * @get_poll_interval: Getter for the #Occ:poll-interval property.
+ * @get_state: Getter for the #Occ:state property.
+ *
+ * Virtual table for the D-Bus interface <link linkend="gdbus-interface-org-openbmc-Occ.top_of_page">org.openbmc.Occ</link>.
+ */
+
+typedef OccIface OccInterface;
+G_DEFINE_INTERFACE (Occ, occ, G_TYPE_OBJECT);
+
+static void
+occ_default_init (OccIface *iface)
+{
+ /* GObject signals for incoming D-Bus method calls: */
+ /**
+ * Occ::handle-init:
+ * @object: A #Occ.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-openbmc-Occ.init">init()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call occ_complete_init() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-init",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OccIface, handle_init),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /**
+ * Occ::handle-collect:
+ * @object: A #Occ.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-openbmc-Occ.collect">collect()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call occ_complete_collect() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-collect",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OccIface, handle_collect),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /* GObject properties for D-Bus properties: */
+ /**
+ * Occ:state:
+ *
+ * Represents the D-Bus property <link linkend="gdbus-property-org-openbmc-Occ.state">"state"</link>.
+ *
+ * Since the D-Bus property for this #GObject property is both readable and writable, it is meaningful to both read from it and write to it on both the service- and client-side.
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_string ("state", "state", "state", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * Occ:instance-name:
+ *
+ * Represents the D-Bus property <link linkend="gdbus-property-org-openbmc-Occ.instance_name">"instance_name"</link>.
+ *
+ * Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side.
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_string ("instance-name", "instance_name", "instance_name", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * Occ:poll-interval:
+ *
+ * Represents the D-Bus property <link linkend="gdbus-property-org-openbmc-Occ.poll_interval">"poll_interval"</link>.
+ *
+ * Since the D-Bus property for this #GObject property is both readable and writable, it is meaningful to both read from it and write to it on both the service- and client-side.
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_int ("poll-interval", "poll_interval", "poll_interval", G_MININT32, G_MAXINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * occ_get_state: (skip)
+ * @object: A #Occ.
+ *
+ * Gets the value of the <link linkend="gdbus-property-org-openbmc-Occ.state">"state"</link> D-Bus property.
+ *
+ * Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side.
+ *
+ * <warning>The returned value is only valid until the property changes so on the client-side it is only safe to use this function on the thread where @object was constructed. Use occ_dup_state() if on another thread.</warning>
+ *
+ * Returns: (transfer none): The property value or %NULL if the property is not set. Do not free the returned value, it belongs to @object.
+ */
+const gchar *
+occ_get_state (Occ *object)
+{
+ return OCC_GET_IFACE (object)->get_state (object);
+}
+
+/**
+ * occ_dup_state: (skip)
+ * @object: A #Occ.
+ *
+ * Gets a copy of the <link linkend="gdbus-property-org-openbmc-Occ.state">"state"</link> D-Bus property.
+ *
+ * Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side.
+ *
+ * Returns: (transfer full): The property value or %NULL if the property is not set. The returned value should be freed with g_free().
+ */
+gchar *
+occ_dup_state (Occ *object)
+{
+ gchar *value;
+ g_object_get (G_OBJECT (object), "state", &value, NULL);
+ return value;
+}
+
+/**
+ * occ_set_state: (skip)
+ * @object: A #Occ.
+ * @value: The value to set.
+ *
+ * Sets the <link linkend="gdbus-property-org-openbmc-Occ.state">"state"</link> D-Bus property to @value.
+ *
+ * Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side.
+ */
+void
+occ_set_state (Occ *object, const gchar *value)
+{
+ g_object_set (G_OBJECT (object), "state", value, NULL);
+}
+
+/**
+ * occ_get_instance_name: (skip)
+ * @object: A #Occ.
+ *
+ * Gets the value of the <link linkend="gdbus-property-org-openbmc-Occ.instance_name">"instance_name"</link> D-Bus property.
+ *
+ * Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side.
+ *
+ * <warning>The returned value is only valid until the property changes so on the client-side it is only safe to use this function on the thread where @object was constructed. Use occ_dup_instance_name() if on another thread.</warning>
+ *
+ * Returns: (transfer none): The property value or %NULL if the property is not set. Do not free the returned value, it belongs to @object.
+ */
+const gchar *
+occ_get_instance_name (Occ *object)
+{
+ return OCC_GET_IFACE (object)->get_instance_name (object);
+}
+
+/**
+ * occ_dup_instance_name: (skip)
+ * @object: A #Occ.
+ *
+ * Gets a copy of the <link linkend="gdbus-property-org-openbmc-Occ.instance_name">"instance_name"</link> D-Bus property.
+ *
+ * Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side.
+ *
+ * Returns: (transfer full): The property value or %NULL if the property is not set. The returned value should be freed with g_free().
+ */
+gchar *
+occ_dup_instance_name (Occ *object)
+{
+ gchar *value;
+ g_object_get (G_OBJECT (object), "instance-name", &value, NULL);
+ return value;
+}
+
+/**
+ * occ_set_instance_name: (skip)
+ * @object: A #Occ.
+ * @value: The value to set.
+ *
+ * Sets the <link linkend="gdbus-property-org-openbmc-Occ.instance_name">"instance_name"</link> D-Bus property to @value.
+ *
+ * Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side.
+ */
+void
+occ_set_instance_name (Occ *object, const gchar *value)
+{
+ g_object_set (G_OBJECT (object), "instance-name", value, NULL);
+}
+
+/**
+ * occ_get_poll_interval: (skip)
+ * @object: A #Occ.
+ *
+ * Gets the value of the <link linkend="gdbus-property-org-openbmc-Occ.poll_interval">"poll_interval"</link> D-Bus property.
+ *
+ * Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side.
+ *
+ * Returns: The property value.
+ */
+gint
+occ_get_poll_interval (Occ *object)
+{
+ return OCC_GET_IFACE (object)->get_poll_interval (object);
+}
+
+/**
+ * occ_set_poll_interval: (skip)
+ * @object: A #Occ.
+ * @value: The value to set.
+ *
+ * Sets the <link linkend="gdbus-property-org-openbmc-Occ.poll_interval">"poll_interval"</link> D-Bus property to @value.
+ *
+ * Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side.
+ */
+void
+occ_set_poll_interval (Occ *object, gint value)
+{
+ g_object_set (G_OBJECT (object), "poll-interval", value, NULL);
+}
+
+/**
+ * occ_call_init:
+ * @proxy: A #OccProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-openbmc-Occ.init">init()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call occ_call_init_finish() to get the result of the operation.
+ *
+ * See occ_call_init_sync() for the synchronous, blocking version of this method.
+ */
+void
+occ_call_init (
+ Occ *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "init",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * occ_call_init_finish:
+ * @proxy: A #OccProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to occ_call_init().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with occ_call_init().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+occ_call_init_finish (
+ Occ *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * occ_call_init_sync:
+ * @proxy: A #OccProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-openbmc-Occ.init">init()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See occ_call_init() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+occ_call_init_sync (
+ Occ *proxy,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "init",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * occ_call_collect:
+ * @proxy: A #OccProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-openbmc-Occ.collect">collect()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call occ_call_collect_finish() to get the result of the operation.
+ *
+ * See occ_call_collect_sync() for the synchronous, blocking version of this method.
+ */
+void
+occ_call_collect (
+ Occ *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "collect",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * occ_call_collect_finish:
+ * @proxy: A #OccProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to occ_call_collect().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with occ_call_collect().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+occ_call_collect_finish (
+ Occ *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * occ_call_collect_sync:
+ * @proxy: A #OccProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-openbmc-Occ.collect">collect()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See occ_call_collect() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+occ_call_collect_sync (
+ Occ *proxy,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "collect",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * occ_complete_init:
+ * @object: A #Occ.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-openbmc-Occ.init">init()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+occ_complete_init (
+ Occ *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/**
+ * occ_complete_collect:
+ * @object: A #Occ.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-openbmc-Occ.collect">collect()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+occ_complete_collect (
+ Occ *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * OccProxy:
+ *
+ * The #OccProxy structure contains only private data and should only be accessed using the provided API.
+ */
+
+/**
+ * OccProxyClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #OccProxy.
+ */
+
+struct _OccProxyPrivate
+{
+ GData *qdata;
+};
+
+static void occ_proxy_iface_init (OccIface *iface);
+
+#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38
+G_DEFINE_TYPE_WITH_CODE (OccProxy, occ_proxy, G_TYPE_DBUS_PROXY,
+ G_ADD_PRIVATE (OccProxy)
+ G_IMPLEMENT_INTERFACE (TYPE_OCC, occ_proxy_iface_init));
+
+#else
+G_DEFINE_TYPE_WITH_CODE (OccProxy, occ_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (TYPE_OCC, occ_proxy_iface_init));
+
+#endif
+static void
+occ_proxy_finalize (GObject *object)
+{
+ OccProxy *proxy = OCC_PROXY (object);
+ g_datalist_clear (&proxy->priv->qdata);
+ G_OBJECT_CLASS (occ_proxy_parent_class)->finalize (object);
+}
+
+static void
+occ_proxy_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec G_GNUC_UNUSED)
+{
+ const _ExtendedGDBusPropertyInfo *info;
+ GVariant *variant;
+ g_assert (prop_id != 0 && prop_id - 1 < 3);
+ info = _occ_property_info_pointers[prop_id - 1];
+ variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name);
+ if (info->use_gvariant)
+ {
+ g_value_set_variant (value, variant);
+ }
+ else
+ {
+ if (variant != NULL)
+ g_dbus_gvariant_to_gvalue (variant, value);
+ }
+ if (variant != NULL)
+ g_variant_unref (variant);
+}
+
+static void
+occ_proxy_set_property_cb (GDBusProxy *proxy,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ const _ExtendedGDBusPropertyInfo *info = user_data;
+ GError *error;
+ GVariant *_ret;
+ error = NULL;
+ _ret = g_dbus_proxy_call_finish (proxy, res, &error);
+ if (!_ret)
+ {
+ g_warning ("Error setting property '%s' on interface org.openbmc.Occ: %s (%s, %d)",
+ info->parent_struct.name,
+ error->message, g_quark_to_string (error->domain), error->code);
+ g_error_free (error);
+ }
+ else
+ {
+ g_variant_unref (_ret);
+ }
+}
+
+static void
+occ_proxy_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec G_GNUC_UNUSED)
+{
+ const _ExtendedGDBusPropertyInfo *info;
+ GVariant *variant;
+ g_assert (prop_id != 0 && prop_id - 1 < 3);
+ info = _occ_property_info_pointers[prop_id - 1];
+ variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature));
+ g_dbus_proxy_call (G_DBUS_PROXY (object),
+ "org.freedesktop.DBus.Properties.Set",
+ g_variant_new ("(ssv)", "org.openbmc.Occ", info->parent_struct.name, variant),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL, (GAsyncReadyCallback) occ_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct);
+ g_variant_unref (variant);
+}
+
+static void
+occ_proxy_g_signal (GDBusProxy *proxy,
+ const gchar *sender_name G_GNUC_UNUSED,
+ const gchar *signal_name,
+ GVariant *parameters)
+{
+ _ExtendedGDBusSignalInfo *info;
+ GVariantIter iter;
+ GVariant *child;
+ GValue *paramv;
+ guint num_params;
+ guint n;
+ guint signal_id;
+ info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_occ_interface_info.parent_struct, signal_name);
+ if (info == NULL)
+ return;
+ num_params = g_variant_n_children (parameters);
+ paramv = g_new0 (GValue, num_params + 1);
+ g_value_init (¶mv[0], TYPE_OCC);
+ g_value_set_object (¶mv[0], proxy);
+ g_variant_iter_init (&iter, parameters);
+ n = 1;
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1];
+ if (arg_info->use_gvariant)
+ {
+ g_value_init (¶mv[n], G_TYPE_VARIANT);
+ g_value_set_variant (¶mv[n], child);
+ n++;
+ }
+ else
+ g_dbus_gvariant_to_gvalue (child, ¶mv[n++]);
+ g_variant_unref (child);
+ }
+ signal_id = g_signal_lookup (info->signal_name, TYPE_OCC);
+ g_signal_emitv (paramv, signal_id, 0, NULL);
+ for (n = 0; n < num_params + 1; n++)
+ g_value_unset (¶mv[n]);
+ g_free (paramv);
+}
+
+static void
+occ_proxy_g_properties_changed (GDBusProxy *_proxy,
+ GVariant *changed_properties,
+ const gchar *const *invalidated_properties)
+{
+ OccProxy *proxy = OCC_PROXY (_proxy);
+ guint n;
+ const gchar *key;
+ GVariantIter *iter;
+ _ExtendedGDBusPropertyInfo *info;
+ g_variant_get (changed_properties, "a{sv}", &iter);
+ while (g_variant_iter_next (iter, "{&sv}", &key, NULL))
+ {
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_occ_interface_info.parent_struct, key);
+ g_datalist_remove_data (&proxy->priv->qdata, key);
+ if (info != NULL)
+ g_object_notify (G_OBJECT (proxy), info->hyphen_name);
+ }
+ g_variant_iter_free (iter);
+ for (n = 0; invalidated_properties[n] != NULL; n++)
+ {
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_occ_interface_info.parent_struct, invalidated_properties[n]);
+ g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]);
+ if (info != NULL)
+ g_object_notify (G_OBJECT (proxy), info->hyphen_name);
+ }
+}
+
+static const gchar *
+occ_proxy_get_state (Occ *object)
+{
+ OccProxy *proxy = OCC_PROXY (object);
+ GVariant *variant;
+ const gchar *value = NULL;
+ variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "state");
+ if (variant != NULL)
+ {
+ value = g_variant_get_string (variant, NULL);
+ g_variant_unref (variant);
+ }
+ return value;
+}
+
+static const gchar *
+occ_proxy_get_instance_name (Occ *object)
+{
+ OccProxy *proxy = OCC_PROXY (object);
+ GVariant *variant;
+ const gchar *value = NULL;
+ variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "instance_name");
+ if (variant != NULL)
+ {
+ value = g_variant_get_string (variant, NULL);
+ g_variant_unref (variant);
+ }
+ return value;
+}
+
+static gint
+occ_proxy_get_poll_interval (Occ *object)
+{
+ OccProxy *proxy = OCC_PROXY (object);
+ GVariant *variant;
+ gint value = 0;
+ variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "poll_interval");
+ if (variant != NULL)
+ {
+ value = g_variant_get_int32 (variant);
+ g_variant_unref (variant);
+ }
+ return value;
+}
+
+static void
+occ_proxy_init (OccProxy *proxy)
+{
+#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38
+ proxy->priv = occ_proxy_get_instance_private (proxy);
+#else
+ proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, TYPE_OCC_PROXY, OccProxyPrivate);
+#endif
+
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), occ_interface_info ());
+}
+
+static void
+occ_proxy_class_init (OccProxyClass *klass)
+{
+ GObjectClass *gobject_class;
+ GDBusProxyClass *proxy_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = occ_proxy_finalize;
+ gobject_class->get_property = occ_proxy_get_property;
+ gobject_class->set_property = occ_proxy_set_property;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = occ_proxy_g_signal;
+ proxy_class->g_properties_changed = occ_proxy_g_properties_changed;
+
+ occ_override_properties (gobject_class, 1);
+
+#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38
+ g_type_class_add_private (klass, sizeof (OccProxyPrivate));
+#endif
+}
+
+static void
+occ_proxy_iface_init (OccIface *iface)
+{
+ iface->get_state = occ_proxy_get_state;
+ iface->get_instance_name = occ_proxy_get_instance_name;
+ iface->get_poll_interval = occ_proxy_get_poll_interval;
+}
+
+/**
+ * occ_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-org-openbmc-Occ.top_of_page">org.openbmc.Occ</link>. See g_dbus_proxy_new() for more details.
+ *
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call occ_proxy_new_finish() to get the result of the operation.
+ *
+ * See occ_proxy_new_sync() for the synchronous, blocking version of this constructor.
+ */
+void
+occ_proxy_new (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (TYPE_OCC_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.openbmc.Occ", NULL);
+}
+
+/**
+ * occ_proxy_new_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to occ_proxy_new().
+ * @error: Return location for error or %NULL
+ *
+ * Finishes an operation started with occ_proxy_new().
+ *
+ * Returns: (transfer full) (type OccProxy): The constructed proxy object or %NULL if @error is set.
+ */
+Occ *
+occ_proxy_new_finish (
+ GAsyncResult *res,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (res);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
+ g_object_unref (source_object);
+ if (ret != NULL)
+ return OCC (ret);
+ else
+ return NULL;
+}
+
+/**
+ * occ_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL
+ *
+ * Synchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-org-openbmc-Occ.top_of_page">org.openbmc.Occ</link>. See g_dbus_proxy_new_sync() for more details.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * See occ_proxy_new() for the asynchronous version of this constructor.
+ *
+ * Returns: (transfer full) (type OccProxy): The constructed proxy object or %NULL if @error is set.
+ */
+Occ *
+occ_proxy_new_sync (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInitable *ret;
+ ret = g_initable_new (TYPE_OCC_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.openbmc.Occ", NULL);
+ if (ret != NULL)
+ return OCC (ret);
+ else
+ return NULL;
+}
+
+
+/**
+ * occ_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like occ_proxy_new() but takes a #GBusType instead of a #GDBusConnection.
+ *
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call occ_proxy_new_for_bus_finish() to get the result of the operation.
+ *
+ * See occ_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor.
+ */
+void
+occ_proxy_new_for_bus (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (TYPE_OCC_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.openbmc.Occ", NULL);
+}
+
+/**
+ * occ_proxy_new_for_bus_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to occ_proxy_new_for_bus().
+ * @error: Return location for error or %NULL
+ *
+ * Finishes an operation started with occ_proxy_new_for_bus().
+ *
+ * Returns: (transfer full) (type OccProxy): The constructed proxy object or %NULL if @error is set.
+ */
+Occ *
+occ_proxy_new_for_bus_finish (
+ GAsyncResult *res,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (res);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
+ g_object_unref (source_object);
+ if (ret != NULL)
+ return OCC (ret);
+ else
+ return NULL;
+}
+
+/**
+ * occ_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL
+ *
+ * Like occ_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * See occ_proxy_new_for_bus() for the asynchronous version of this constructor.
+ *
+ * Returns: (transfer full) (type OccProxy): The constructed proxy object or %NULL if @error is set.
+ */
+Occ *
+occ_proxy_new_for_bus_sync (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInitable *ret;
+ ret = g_initable_new (TYPE_OCC_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.openbmc.Occ", NULL);
+ if (ret != NULL)
+ return OCC (ret);
+ else
+ return NULL;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * OccSkeleton:
+ *
+ * The #OccSkeleton structure contains only private data and should only be accessed using the provided API.
+ */
+
+/**
+ * OccSkeletonClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #OccSkeleton.
+ */
+
+struct _OccSkeletonPrivate
+{
+ GValue *properties;
+ GList *changed_properties;
+ GSource *changed_properties_idle_source;
+ GMainContext *context;
+ GMutex lock;
+};
+
+static void
+_occ_skeleton_handle_method_call (
+ GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *sender G_GNUC_UNUSED,
+ const gchar *object_path G_GNUC_UNUSED,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (user_data);
+ _ExtendedGDBusMethodInfo *info;
+ GVariantIter iter;
+ GVariant *child;
+ GValue *paramv;
+ guint num_params;
+ guint num_extra;
+ guint n;
+ guint signal_id;
+ GValue return_value = G_VALUE_INIT;
+ info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation);
+ g_assert (info != NULL);
+ num_params = g_variant_n_children (parameters);
+ num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra);
+ n = 0;
+ g_value_init (¶mv[n], TYPE_OCC);
+ g_value_set_object (¶mv[n++], skeleton);
+ g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION);
+ g_value_set_object (¶mv[n++], invocation);
+ if (info->pass_fdlist)
+ {
+#ifdef G_OS_UNIX
+ g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST);
+ g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));
+#else
+ g_assert_not_reached ();
+#endif
+ }
+ g_variant_iter_init (&iter, parameters);
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];
+ if (arg_info->use_gvariant)
+ {
+ g_value_init (¶mv[n], G_TYPE_VARIANT);
+ g_value_set_variant (¶mv[n], child);
+ n++;
+ }
+ else
+ g_dbus_gvariant_to_gvalue (child, ¶mv[n++]);
+ g_variant_unref (child);
+ }
+ signal_id = g_signal_lookup (info->signal_name, TYPE_OCC);
+ g_value_init (&return_value, G_TYPE_BOOLEAN);
+ g_signal_emitv (paramv, signal_id, 0, &return_value);
+ if (!g_value_get_boolean (&return_value))
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);
+ g_value_unset (&return_value);
+ for (n = 0; n < num_params + num_extra; n++)
+ g_value_unset (¶mv[n]);
+ g_free (paramv);
+}
+
+static GVariant *
+_occ_skeleton_handle_get_property (
+ GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *sender G_GNUC_UNUSED,
+ const gchar *object_path G_GNUC_UNUSED,
+ const gchar *interface_name G_GNUC_UNUSED,
+ const gchar *property_name,
+ GError **error,
+ gpointer user_data)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (user_data);
+ GValue value = G_VALUE_INIT;
+ GParamSpec *pspec;
+ _ExtendedGDBusPropertyInfo *info;
+ GVariant *ret;
+ ret = NULL;
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_occ_interface_info.parent_struct, property_name);
+ g_assert (info != NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
+ if (pspec == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
+ }
+ else
+ {
+ g_value_init (&value, pspec->value_type);
+ g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value);
+ ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature));
+ g_value_unset (&value);
+ }
+ return ret;
+}
+
+static gboolean
+_occ_skeleton_handle_set_property (
+ GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *sender G_GNUC_UNUSED,
+ const gchar *object_path G_GNUC_UNUSED,
+ const gchar *interface_name G_GNUC_UNUSED,
+ const gchar *property_name,
+ GVariant *variant,
+ GError **error,
+ gpointer user_data)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (user_data);
+ GValue value = G_VALUE_INIT;
+ GParamSpec *pspec;
+ _ExtendedGDBusPropertyInfo *info;
+ gboolean ret;
+ ret = FALSE;
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_occ_interface_info.parent_struct, property_name);
+ g_assert (info != NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
+ if (pspec == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
+ }
+ else
+ {
+ if (info->use_gvariant)
+ g_value_set_variant (&value, variant);
+ else
+ g_dbus_gvariant_to_gvalue (variant, &value);
+ g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value);
+ g_value_unset (&value);
+ ret = TRUE;
+ }
+ return ret;
+}
+
+static const GDBusInterfaceVTable _occ_skeleton_vtable =
+{
+ _occ_skeleton_handle_method_call,
+ _occ_skeleton_handle_get_property,
+ _occ_skeleton_handle_set_property,
+ {NULL}
+};
+
+static GDBusInterfaceInfo *
+occ_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)
+{
+ return occ_interface_info ();
+}
+
+static GDBusInterfaceVTable *
+occ_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)
+{
+ return (GDBusInterfaceVTable *) &_occ_skeleton_vtable;
+}
+
+static GVariant *
+occ_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (_skeleton);
+
+ GVariantBuilder builder;
+ guint n;
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ if (_occ_interface_info.parent_struct.properties == NULL)
+ goto out;
+ for (n = 0; _occ_interface_info.parent_struct.properties[n] != NULL; n++)
+ {
+ GDBusPropertyInfo *info = _occ_interface_info.parent_struct.properties[n];
+ if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
+ {
+ GVariant *value;
+ value = _occ_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.openbmc.Occ", info->name, NULL, skeleton);
+ if (value != NULL)
+ {
+ g_variant_take_ref (value);
+ g_variant_builder_add (&builder, "{sv}", info->name, value);
+ g_variant_unref (value);
+ }
+ }
+ }
+out:
+ return g_variant_builder_end (&builder);
+}
+
+static gboolean _occ_emit_changed (gpointer user_data);
+
+static void
+occ_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (_skeleton);
+ gboolean emit_changed = FALSE;
+
+ g_mutex_lock (&skeleton->priv->lock);
+ if (skeleton->priv->changed_properties_idle_source != NULL)
+ {
+ g_source_destroy (skeleton->priv->changed_properties_idle_source);
+ skeleton->priv->changed_properties_idle_source = NULL;
+ emit_changed = TRUE;
+ }
+ g_mutex_unlock (&skeleton->priv->lock);
+
+ if (emit_changed)
+ _occ_emit_changed (skeleton);
+}
+
+static void occ_skeleton_iface_init (OccIface *iface);
+#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38
+G_DEFINE_TYPE_WITH_CODE (OccSkeleton, occ_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,
+ G_ADD_PRIVATE (OccSkeleton)
+ G_IMPLEMENT_INTERFACE (TYPE_OCC, occ_skeleton_iface_init));
+
+#else
+G_DEFINE_TYPE_WITH_CODE (OccSkeleton, occ_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,
+ G_IMPLEMENT_INTERFACE (TYPE_OCC, occ_skeleton_iface_init));
+
+#endif
+static void
+occ_skeleton_finalize (GObject *object)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (object);
+ guint n;
+ for (n = 0; n < 3; n++)
+ g_value_unset (&skeleton->priv->properties[n]);
+ g_free (skeleton->priv->properties);
+ g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);
+ if (skeleton->priv->changed_properties_idle_source != NULL)
+ g_source_destroy (skeleton->priv->changed_properties_idle_source);
+ g_main_context_unref (skeleton->priv->context);
+ g_mutex_clear (&skeleton->priv->lock);
+ G_OBJECT_CLASS (occ_skeleton_parent_class)->finalize (object);
+}
+
+static void
+occ_skeleton_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec G_GNUC_UNUSED)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (object);
+ g_assert (prop_id != 0 && prop_id - 1 < 3);
+ g_mutex_lock (&skeleton->priv->lock);
+ g_value_copy (&skeleton->priv->properties[prop_id - 1], value);
+ g_mutex_unlock (&skeleton->priv->lock);
+}
+
+static gboolean
+_occ_emit_changed (gpointer user_data)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (user_data);
+ GList *l;
+ GVariantBuilder builder;
+ GVariantBuilder invalidated_builder;
+ guint num_changes;
+
+ g_mutex_lock (&skeleton->priv->lock);
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
+ for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next)
+ {
+ ChangedProperty *cp = l->data;
+ GVariant *variant;
+ const GValue *cur_value;
+
+ cur_value = &skeleton->priv->properties[cp->prop_id - 1];
+ if (!_g_value_equal (cur_value, &cp->orig_value))
+ {
+ variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature));
+ g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant);
+ g_variant_unref (variant);
+ num_changes++;
+ }
+ }
+ if (num_changes > 0)
+ {
+ GList *connections, *ll;
+ GVariant *signal_variant;
+ signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "org.openbmc.Occ",
+ &builder, &invalidated_builder));
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+ for (ll = connections; ll != NULL; ll = ll->next)
+ {
+ GDBusConnection *connection = ll->data;
+
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)),
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ signal_variant,
+ NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+ }
+ else
+ {
+ g_variant_builder_clear (&builder);
+ g_variant_builder_clear (&invalidated_builder);
+ }
+ g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);
+ skeleton->priv->changed_properties = NULL;
+ skeleton->priv->changed_properties_idle_source = NULL;
+ g_mutex_unlock (&skeleton->priv->lock);
+ return FALSE;
+}
+
+static void
+_occ_schedule_emit_changed (OccSkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value)
+{
+ ChangedProperty *cp;
+ GList *l;
+ cp = NULL;
+ for (l = skeleton->priv->changed_properties; l != NULL; l = l->next)
+ {
+ ChangedProperty *i_cp = l->data;
+ if (i_cp->info == info)
+ {
+ cp = i_cp;
+ break;
+ }
+ }
+ if (cp == NULL)
+ {
+ cp = g_new0 (ChangedProperty, 1);
+ cp->prop_id = prop_id;
+ cp->info = info;
+ skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp);
+ g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value));
+ g_value_copy (orig_value, &cp->orig_value);
+ }
+}
+
+static void
+occ_skeleton_notify (GObject *object,
+ GParamSpec *pspec G_GNUC_UNUSED)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (object);
+ g_mutex_lock (&skeleton->priv->lock);
+ if (skeleton->priv->changed_properties != NULL &&
+ skeleton->priv->changed_properties_idle_source == NULL)
+ {
+ skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
+ g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
+ g_source_set_callback (skeleton->priv->changed_properties_idle_source, _occ_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _occ_emit_changed");
+ g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
+ g_source_unref (skeleton->priv->changed_properties_idle_source);
+ }
+ g_mutex_unlock (&skeleton->priv->lock);
+}
+
+static void
+occ_skeleton_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (object);
+ g_assert (prop_id != 0 && prop_id - 1 < 3);
+ g_mutex_lock (&skeleton->priv->lock);
+ g_object_freeze_notify (object);
+ if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1]))
+ {
+ if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL)
+ _occ_schedule_emit_changed (skeleton, _occ_property_info_pointers[prop_id - 1], prop_id, &skeleton->priv->properties[prop_id - 1]);
+ g_value_copy (value, &skeleton->priv->properties[prop_id - 1]);
+ g_object_notify_by_pspec (object, pspec);
+ }
+ g_mutex_unlock (&skeleton->priv->lock);
+ g_object_thaw_notify (object);
+}
+
+static void
+occ_skeleton_init (OccSkeleton *skeleton)
+{
+#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38
+ skeleton->priv = occ_skeleton_get_instance_private (skeleton);
+#else
+ skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, TYPE_OCC_SKELETON, OccSkeletonPrivate);
+#endif
+
+ g_mutex_init (&skeleton->priv->lock);
+ skeleton->priv->context = g_main_context_ref_thread_default ();
+ skeleton->priv->properties = g_new0 (GValue, 3);
+ g_value_init (&skeleton->priv->properties[0], G_TYPE_STRING);
+ g_value_init (&skeleton->priv->properties[1], G_TYPE_STRING);
+ g_value_init (&skeleton->priv->properties[2], G_TYPE_INT);
+}
+
+static const gchar *
+occ_skeleton_get_state (Occ *object)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (object);
+ const gchar *value;
+ g_mutex_lock (&skeleton->priv->lock);
+ value = g_value_get_string (&(skeleton->priv->properties[0]));
+ g_mutex_unlock (&skeleton->priv->lock);
+ return value;
+}
+
+static const gchar *
+occ_skeleton_get_instance_name (Occ *object)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (object);
+ const gchar *value;
+ g_mutex_lock (&skeleton->priv->lock);
+ value = g_value_get_string (&(skeleton->priv->properties[1]));
+ g_mutex_unlock (&skeleton->priv->lock);
+ return value;
+}
+
+static gint
+occ_skeleton_get_poll_interval (Occ *object)
+{
+ OccSkeleton *skeleton = OCC_SKELETON (object);
+ gint value;
+ g_mutex_lock (&skeleton->priv->lock);
+ value = g_value_get_int (&(skeleton->priv->properties[2]));
+ g_mutex_unlock (&skeleton->priv->lock);
+ return value;
+}
+
+static void
+occ_skeleton_class_init (OccSkeletonClass *klass)
+{
+ GObjectClass *gobject_class;
+ GDBusInterfaceSkeletonClass *skeleton_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = occ_skeleton_finalize;
+ gobject_class->get_property = occ_skeleton_get_property;
+ gobject_class->set_property = occ_skeleton_set_property;
+ gobject_class->notify = occ_skeleton_notify;
+
+
+ occ_override_properties (gobject_class, 1);
+
+ skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
+ skeleton_class->get_info = occ_skeleton_dbus_interface_get_info;
+ skeleton_class->get_properties = occ_skeleton_dbus_interface_get_properties;
+ skeleton_class->flush = occ_skeleton_dbus_interface_flush;
+ skeleton_class->get_vtable = occ_skeleton_dbus_interface_get_vtable;
+
+#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38
+ g_type_class_add_private (klass, sizeof (OccSkeletonPrivate));
+#endif
+}
+
+static void
+occ_skeleton_iface_init (OccIface *iface)
+{
+ iface->get_state = occ_skeleton_get_state;
+ iface->get_instance_name = occ_skeleton_get_instance_name;
+ iface->get_poll_interval = occ_skeleton_get_poll_interval;
+}
+
+/**
+ * occ_skeleton_new:
+ *
+ * Creates a skeleton object for the D-Bus interface <link linkend="gdbus-interface-org-openbmc-Occ.top_of_page">org.openbmc.Occ</link>.
+ *
+ * Returns: (transfer full) (type OccSkeleton): The skeleton object.
+ */
+Occ *
+occ_skeleton_new (void)
+{
+ return OCC (g_object_new (TYPE_OCC_SKELETON, NULL));
+}
+
+/* ------------------------------------------------------------------------
+=======
+>>>>>>> upstream/master
* Code for interface org.openbmc.Fan
* ------------------------------------------------------------------------
*/
@@ -1894,6 +3427,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _fan_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _fan_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -4029,6 +5563,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _sensor_value_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _sensor_value_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -5846,6 +7381,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _sensor_threshold_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _sensor_threshold_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -7032,6 +8568,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _sensor_i2c_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _sensor_i2c_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -8248,6 +9785,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _sensor_match_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _sensor_match_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -10754,6 +12292,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _shared_resource_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _shared_resource_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -12259,6 +13798,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _control_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _control_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -16019,6 +17559,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _control_power_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _control_power_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -16199,11 +17740,42 @@
FALSE
};
+static const _ExtendedGDBusArgInfo _watchdog_method_info_set_IN_ARG_interval =
+{
+ {
+ -1,
+ (gchar *) "interval",
+ (gchar *) "i",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _watchdog_method_info_set_IN_ARG_pointers[] =
+{
+ &_watchdog_method_info_set_IN_ARG_interval,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _watchdog_method_info_set =
+{
+ {
+ -1,
+ (gchar *) "set",
+ (GDBusArgInfo **) &_watchdog_method_info_set_IN_ARG_pointers,
+ NULL,
+ NULL
+ },
+ "handle-set",
+ FALSE
+};
+
static const _ExtendedGDBusMethodInfo * const _watchdog_method_info_pointers[] =
{
&_watchdog_method_info_start,
&_watchdog_method_info_poke,
&_watchdog_method_info_stop,
+ &_watchdog_method_info_set,
NULL
};
@@ -16314,6 +17886,7 @@
* WatchdogIface:
* @parent_iface: The parent interface.
* @handle_poke: Handler for the #Watchdog::handle-poke signal.
+ * @handle_set: Handler for the #Watchdog::handle-set signal.
* @handle_start: Handler for the #Watchdog::handle-start signal.
* @handle_stop: Handler for the #Watchdog::handle-stop signal.
* @get_poll_interval: Getter for the #Watchdog:poll-interval property.
@@ -16396,6 +17969,29 @@
1,
G_TYPE_DBUS_METHOD_INVOCATION);
+ /**
+ * Watchdog::handle-set:
+ * @object: A #Watchdog.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_interval: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-openbmc-Watchdog.set">set()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call watchdog_complete_set() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-set",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (WatchdogIface, handle_set),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_INT);
+
/* GObject signals for received D-Bus signals: */
/**
* Watchdog::watchdog-error:
@@ -16788,6 +18384,104 @@
}
/**
+ * watchdog_call_set:
+ * @proxy: A #WatchdogProxy.
+ * @arg_interval: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-openbmc-Watchdog.set">set()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call watchdog_call_set_finish() to get the result of the operation.
+ *
+ * See watchdog_call_set_sync() for the synchronous, blocking version of this method.
+ */
+void
+watchdog_call_set (
+ Watchdog *proxy,
+ gint arg_interval,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "set",
+ g_variant_new ("(i)",
+ arg_interval),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * watchdog_call_set_finish:
+ * @proxy: A #WatchdogProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to watchdog_call_set().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with watchdog_call_set().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+watchdog_call_set_finish (
+ Watchdog *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * watchdog_call_set_sync:
+ * @proxy: A #WatchdogProxy.
+ * @arg_interval: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-openbmc-Watchdog.set">set()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See watchdog_call_set() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+watchdog_call_set_sync (
+ Watchdog *proxy,
+ gint arg_interval,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "set",
+ g_variant_new ("(i)",
+ arg_interval),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
* watchdog_complete_start:
* @object: A #Watchdog.
* @invocation: (transfer full): A #GDBusMethodInvocation.
@@ -16841,6 +18535,24 @@
g_variant_new ("()"));
}
+/**
+ * watchdog_complete_set:
+ * @object: A #Watchdog.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-openbmc-Watchdog.set">set()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+watchdog_complete_set (
+ Watchdog *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
/* ------------------------------------------------------------------------ */
/**
@@ -17657,6 +19369,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _watchdog_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _watchdog_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -20695,6 +22408,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _flash_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _flash_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -22350,6 +24064,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _flash_control_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _flash_control_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -24062,6 +25777,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _button_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _button_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
@@ -25770,6 +27486,7 @@
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _led_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
+ g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _led_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
diff --git a/interfaces/openbmc_intf.h b/interfaces/openbmc_intf.h
index 204920b..c8d251d 100644
--- a/interfaces/openbmc_intf.h
+++ b/interfaces/openbmc_intf.h
@@ -1,5 +1,5 @@
/*
- * Generated by gdbus-codegen 2.40.2. DO NOT EDIT.
+ * Generated by gdbus-codegen 2.44.1. DO NOT EDIT.
*
* The license of this code is the same as for the source it was derived from.
*/
@@ -2157,6 +2157,11 @@
Watchdog *object,
GDBusMethodInvocation *invocation);
+ gboolean (*handle_set) (
+ Watchdog *object,
+ GDBusMethodInvocation *invocation,
+ gint arg_interval);
+
gboolean (*handle_start) (
Watchdog *object,
GDBusMethodInvocation *invocation);
@@ -2193,6 +2198,10 @@
Watchdog *object,
GDBusMethodInvocation *invocation);
+void watchdog_complete_set (
+ Watchdog *object,
+ GDBusMethodInvocation *invocation);
+
/* D-Bus signal emissions functions: */
@@ -2250,6 +2259,24 @@
GCancellable *cancellable,
GError **error);
+void watchdog_call_set (
+ Watchdog *proxy,
+ gint arg_interval,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean watchdog_call_set_finish (
+ Watchdog *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean watchdog_call_set_sync (
+ Watchdog *proxy,
+ gint arg_interval,
+ GCancellable *cancellable,
+ GError **error);
+
/* D-Bus property accessors: */
diff --git a/objects/host_watchdog_obj.c b/objects/host_watchdog_obj.c
index 65c5fa4..e4e4bab 100644
--- a/objects/host_watchdog_obj.c
+++ b/objects/host_watchdog_obj.c
@@ -31,12 +31,24 @@
}
static gboolean
+set_poll_interval (Watchdog *wd,
+ GDBusMethodInvocation *invocation,
+ guint interval,
+ gpointer user_data)
+{
+ g_print("Setting watchdog poll interval to: %d\n", interval);
+ watchdog_set_poll_interval(wd, interval);
+ watchdog_complete_set(wd,invocation);
+}
+
+static gboolean
on_start (Watchdog *wd,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
watchdog_set_watchdog(wd,1);
guint poll_interval = watchdog_get_poll_interval(wd);
+ g_print("Starting watchdog with poll interval: %d\n", poll_interval);
g_timeout_add(poll_interval, poll_watchdog, user_data);
watchdog_complete_start(wd,invocation);
return TRUE;
@@ -94,6 +106,10 @@
G_CALLBACK (on_poke),
object); /* user_data */
+ g_signal_connect (wd,
+ "handle-set",
+ G_CALLBACK (set_poll_interval),
+ object); /* user_data */
/* Export the object (@manager takes its own reference to @object) */
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
diff --git a/xml/openbmc_intf.xml b/xml/openbmc_intf.xml
index 6fb726b..7711a09 100644
--- a/xml/openbmc_intf.xml
+++ b/xml/openbmc_intf.xml
@@ -123,6 +123,9 @@
<method name="start"/>
<method name="poke"/>
<method name="stop"/>
+ <method name="set"/>
+ <arg direction="in" type="i" name="interval" />
+ </method>
<property name="watchdog" type="i" access="readwrite"/>
<property name="poll_interval" type="i" access="readwrite"/>
<signal name="WatchdogError"/>