提交 3ae0ab67 编写于 作者: D Daniel P. Berrange

Extend RPC server to allow FD passing

The RPC server classes are extended to allow FDs to be received
from clients with calls. There is not currently any way for a
procedure to pass FDs back to the client with replies

* daemon/remote.c, src/rpc/gendispatch.pl: Change virNetMessageHeaderPtr
  param to virNetMessagePtr in dispatcher impls
* src/rpc/virnetserver.c, src/rpc/virnetserverclient.c,
  src/rpc/virnetserverprogram.c, src/rpc/virnetserverprogram.h:
  Extend to support FD passing
上级 36a9c83d
此差异已折叠。
......@@ -1191,6 +1191,7 @@ virNetClientHasPassFD;
# virnetmessage.h
virNetMessageClear;
virNetMessageDecodeNumFDs;
virNetMessageDupFD;
virNetMessageEncodeHeader;
virNetMessageEncodePayload;
virNetMessageEncodeNumFDs;
......
......@@ -2348,7 +2348,7 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS = 57, /* skipgen autogen */
REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS = 58, /* autogen autogen */
REMOTE_PROC_GET_HOSTNAME = 59, /* autogen autogen priority:high */
REMOTE_PROC_SUPPORTS_FEATURE = 60, /* autogen autogen priority:high */
REMOTE_PROC_SUPPORTS_FEATURE = 60, /* skipgen autogen priority:high */
REMOTE_PROC_DOMAIN_MIGRATE_PREPARE = 61, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_MIGRATE_PERFORM = 62, /* autogen autogen */
......
......@@ -298,7 +298,7 @@ elsif ($opt_b) {
print "static int ${name}(\n";
print " virNetServerPtr server,\n";
print " virNetServerClientPtr client,\n";
print " virNetMessageHeaderPtr hdr,\n";
print " virNetMessagePtr msg,\n";
print " virNetMessageErrorPtr rerr";
if ($argtype ne "void") {
print ",\n $argtype *args";
......@@ -315,13 +315,13 @@ elsif ($opt_b) {
print "static int ${name}Helper(\n";
print " virNetServerPtr server,\n";
print " virNetServerClientPtr client,\n";
print " virNetMessageHeaderPtr hdr,\n";
print " virNetMessagePtr msg,\n";
print " virNetMessageErrorPtr rerr,\n";
print " void *args$argann,\n";
print " void *ret$retann)\n";
print "{\n";
print " VIR_DEBUG(\"server=%p client=%p hdr=%p rerr=%p args=%p ret=%p\", server, client, hdr, rerr, args, ret);\n";
print " return $name(server, client, hdr, rerr";
print " VIR_DEBUG(\"server=%p client=%p msg=%p rerr=%p args=%p ret=%p\", server, client, msg, rerr, args, ret);\n";
print " return $name(server, client, msg, rerr";
if ($argtype ne "void") {
print ", args";
}
......@@ -750,7 +750,7 @@ elsif ($opt_b) {
print "static int $name(\n";
print " virNetServerPtr server ATTRIBUTE_UNUSED,\n";
print " virNetServerClientPtr client,\n";
print " virNetMessageHeaderPtr hdr ATTRIBUTE_UNUSED,\n";
print " virNetMessagePtr msg ATTRIBUTE_UNUSED,\n";
print " virNetMessageErrorPtr rerr";
if ($argtype ne "void") {
print ",\n $argtype *args";
......@@ -809,7 +809,7 @@ elsif ($opt_b) {
print " if (!(st = virStreamNew(priv->conn, VIR_STREAM_NONBLOCK)))\n";
print " goto cleanup;\n";
print "\n";
print " if (!(stream = daemonCreateClientStream(client, st, remoteProgram, hdr)))\n";
print " if (!(stream = daemonCreateClientStream(client, st, remoteProgram, &msg->header)))\n";
print " goto cleanup;\n";
print "\n";
}
......
......@@ -138,7 +138,8 @@ static void virNetServerHandleJob(void *jobOpaque, void *opaque)
* message types are not expecting replies, so we
* must just log it & drop them
*/
if (job->msg->header.type == VIR_NET_CALL) {
if (job->msg->header.type == VIR_NET_CALL ||
job->msg->header.type == VIR_NET_CALL_WITH_FDS) {
if (virNetServerProgramUnknownError(job->client,
job->msg,
&job->msg->header) < 0)
......
......@@ -770,6 +770,7 @@ readmore:
/* Grab the completed message */
virNetMessagePtr msg = virNetMessageQueueServe(&client->rx);
virNetServerClientFilterPtr filter;
size_t i;
/* Decode the header so we can use it for routing decisions */
if (virNetMessageDecodeHeader(msg) < 0) {
......@@ -778,6 +779,20 @@ readmore:
return;
}
if (msg->header.type == VIR_NET_CALL_WITH_FDS &&
virNetMessageDecodeNumFDs(msg) < 0) {
virNetMessageFree(msg);
client->wantClose = true;
return;
}
for (i = 0 ; i < msg->nfds ; i++) {
if ((msg->fds[i] = virNetSocketRecvFD(client->sock)) < 0) {
virNetMessageFree(msg);
client->wantClose = true;
return;
}
}
PROBE(RPC_SERVER_CLIENT_MSG_RX,
"client=%p len=%zu prog=%u vers=%u proc=%u type=%u status=%u serial=%u",
client, msg->bufferLength,
......@@ -883,6 +898,15 @@ virNetServerClientDispatchWrite(virNetServerClientPtr client)
if (client->tx->bufferOffset == client->tx->bufferLength) {
virNetMessagePtr msg;
size_t i;
for (i = 0 ; i < client->tx->nfds ; i++) {
if (virNetSocketSendFD(client->sock, client->tx->fds[i]) < 0) {
client->wantClose = true;
return;
}
}
#if HAVE_SASL
/* Completed this 'tx' operation, so now read for all
* future rx/tx to be under a SASL SSF layer
......
......@@ -29,6 +29,7 @@
#include "memory.h"
#include "virterror_internal.h"
#include "logging.h"
#include "virfile.h"
#define VIR_FROM_THIS VIR_FROM_RPC
#define virNetError(code, ...) \
......@@ -284,6 +285,7 @@ int virNetServerProgramDispatch(virNetServerProgramPtr prog,
switch (msg->header.type) {
case VIR_NET_CALL:
case VIR_NET_CALL_WITH_FDS:
ret = virNetServerProgramDispatchCall(prog, server, client, msg);
break;
......@@ -314,7 +316,8 @@ int virNetServerProgramDispatch(virNetServerProgramPtr prog,
return ret;
error:
if (msg->header.type == VIR_NET_CALL) {
if (msg->header.type == VIR_NET_CALL ||
msg->header.type == VIR_NET_CALL_WITH_FDS) {
ret = virNetServerProgramSendReplyError(prog, client, msg, &rerr, &msg->header);
} else {
/* Send a dummy reply to free up 'msg' & unblock client rx */
......@@ -355,6 +358,7 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog,
int rv = -1;
virNetServerProgramProcPtr dispatcher;
virNetMessageError rerr;
size_t i;
memset(&rerr, 0, sizeof(rerr));
......@@ -409,7 +413,20 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog,
*
* 'args and 'ret'
*/
rv = (dispatcher->func)(server, client, &msg->header, &rerr, arg, ret);
rv = (dispatcher->func)(server, client, msg, &rerr, arg, ret);
/*
* Clear out the FDs we got from the client, we don't
* want to send them back !
*
* XXX we don't have a way to let dispatcher->func
* return any FDs. Fortunately we don't need this
* capability just yet
*/
for (i = 0 ; i < msg->nfds ; i++)
VIR_FORCE_CLOSE(msg->fds[i]);
VIR_FREE(msg->fds);
msg->nfds = 0;
xdr_free(dispatcher->arg_filter, arg);
......@@ -421,7 +438,7 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog,
/*msg->header.prog = msg->header.prog;*/
/*msg->header.vers = msg->header.vers;*/
/*msg->header.proc = msg->header.proc;*/
msg->header.type = VIR_NET_REPLY;
msg->header.type = msg->nfds ? VIR_NET_REPLY_WITH_FDS : VIR_NET_REPLY;
/*msg->header.serial = msg->header.serial;*/
msg->header.status = VIR_NET_OK;
......@@ -430,6 +447,12 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog,
goto error;
}
if (msg->nfds &&
virNetMessageEncodeNumFDs(msg) < 0) {
xdr_free(dispatcher->ret_filter, ret);
goto error;
}
if (virNetMessageEncodePayload(msg, dispatcher->ret_filter, ret) < 0) {
xdr_free(dispatcher->ret_filter, ret);
goto error;
......
......@@ -41,7 +41,7 @@ typedef virNetServerProgramProc *virNetServerProgramProcPtr;
typedef int (*virNetServerProgramDispatchFunc)(virNetServerPtr server,
virNetServerClientPtr client,
virNetMessageHeaderPtr hdr,
virNetMessagePtr msg,
virNetMessageErrorPtr rerr,
void *args,
void *ret);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册