/*
 * Python bindings for wpa_ctrl (wpa_supplicant/hostapd control interface)
 * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include <Python.h>
#include <structmember.h>

#include "wpa_ctrl.h"


struct wpaspy_obj {
	PyObject_HEAD
	struct wpa_ctrl *ctrl;
	int attached;
};

static PyObject *wpaspy_error;


static int wpaspy_open(struct wpaspy_obj *self, PyObject *args)
{
	const char *path;

	if (!PyArg_ParseTuple(args, "s", &path))
		return -1;
	self->ctrl = wpa_ctrl_open(path);
	if (self->ctrl == NULL)
		return -1;
	self->attached = 0;
	return 0;
}


static void wpaspy_close(struct wpaspy_obj *self)
{
	if (self->ctrl) {
		if (self->attached)
			wpa_ctrl_detach(self->ctrl);
		wpa_ctrl_close(self->ctrl);
		self->ctrl = NULL;
	}

	if (self->ob_type)
		self->ob_type->tp_free((PyObject *) self);
}


static PyObject * wpaspy_request(struct wpaspy_obj *self, PyObject *args)
{
	const char *cmd;
	char buf[4096];
	size_t buflen;
	int ret;

	if (!PyArg_ParseTuple(args, "s", &cmd))
		return NULL;

	buflen = sizeof(buf) - 1;
	ret = wpa_ctrl_request(self->ctrl, cmd, strlen(cmd), buf, &buflen,
			       NULL);
	if (ret == -2) {
		PyErr_SetString(wpaspy_error, "Request timed out");
		return NULL;
	}
	if (ret) {
		PyErr_SetString(wpaspy_error, "Request failed");
		return NULL;
	}

	buf[buflen] = '\0';
	return Py_BuildValue("s", buf);
}


static PyObject * wpaspy_attach(struct wpaspy_obj *self)
{
	int ret;

	if (self->attached)
		Py_RETURN_NONE;

	ret = wpa_ctrl_attach(self->ctrl);
	if (ret) {
		PyErr_SetString(wpaspy_error, "Attach failed");
		return NULL;
	}
	Py_RETURN_NONE;
}


static PyObject * wpaspy_detach(struct wpaspy_obj *self)
{
	int ret;

	if (!self->attached)
		Py_RETURN_NONE;

	ret = wpa_ctrl_detach(self->ctrl);
	if (ret) {
		PyErr_SetString(wpaspy_error, "Detach failed");
		return NULL;
	}
	Py_RETURN_NONE;
}


static PyObject * wpaspy_pending(struct wpaspy_obj *self)
{
	switch (wpa_ctrl_pending(self->ctrl)) {
	case 1:
		Py_RETURN_TRUE;
	case 0:
		Py_RETURN_FALSE;
	default:
		PyErr_SetString(wpaspy_error, "wpa_ctrl_pending failed");
		break;
	}

	return NULL;
}


static PyObject * wpaspy_recv(struct wpaspy_obj *self)
{
	int ret;
	char buf[4096];
	size_t buflen;

	buflen = sizeof(buf) - 1;
	Py_BEGIN_ALLOW_THREADS
	ret = wpa_ctrl_recv(self->ctrl, buf, &buflen);
	Py_END_ALLOW_THREADS

	if (ret) {
		PyErr_SetString(wpaspy_error, "wpa_ctrl_recv failed");
		return NULL;
	}

	buf[buflen] = '\0';
	return Py_BuildValue("s", buf);
}


static PyMethodDef wpaspy_methods[] = {
	{
		"request", (PyCFunction) wpaspy_request, METH_VARARGS,
		"Send a control interface command and return response"
	},
	{
		"attach", (PyCFunction) wpaspy_attach, METH_NOARGS,
		"Attach as an event monitor"
	},
	{
		"detach", (PyCFunction) wpaspy_detach, METH_NOARGS,
		"Detach an event monitor"
	},
	{
		"pending", (PyCFunction) wpaspy_pending, METH_NOARGS,
		"Check whether any events are pending"
	},
	{
		"recv", (PyCFunction) wpaspy_recv, METH_NOARGS,
		"Received pending event"
	},
	{ NULL, NULL, 0, NULL }
};

static PyMemberDef wpaspy_members[] = {
	{
		"attached", T_INT, offsetof(struct wpaspy_obj, attached),
		READONLY,
		"Whether instance is attached as event monitor"
	},
	{ NULL }
};

static PyTypeObject wpaspy_ctrl = {
	PyObject_HEAD_INIT(NULL)
	.tp_name = "wpaspy.Ctrl",
	.tp_basicsize = sizeof(struct wpaspy_obj),
	.tp_getattro = PyObject_GenericGetAttr,
	.tp_setattro = PyObject_GenericSetAttr,
	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
	.tp_methods = wpaspy_methods,
	.tp_members = wpaspy_members,
	.tp_init = (initproc) wpaspy_open,
	.tp_dealloc = (destructor) wpaspy_close,
	.tp_new = PyType_GenericNew,
};


static PyMethodDef module_methods[] = {
	{ NULL, NULL, 0, NULL }
};


PyMODINIT_FUNC initwpaspy(void)
{
	PyObject *mod;

	PyType_Ready(&wpaspy_ctrl);
	mod = Py_InitModule("wpaspy", module_methods);
	wpaspy_error = PyErr_NewException("wpaspy.error", NULL, NULL);

	Py_INCREF(&wpaspy_ctrl);
	Py_INCREF(wpaspy_error);

	PyModule_AddObject(mod, "Ctrl", (PyObject *) &wpaspy_ctrl);
	PyModule_AddObject(mod, "error", wpaspy_error);
}
