提交 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; ...@@ -1191,6 +1191,7 @@ virNetClientHasPassFD;
# virnetmessage.h # virnetmessage.h
virNetMessageClear; virNetMessageClear;
virNetMessageDecodeNumFDs; virNetMessageDecodeNumFDs;
virNetMessageDupFD;
virNetMessageEncodeHeader; virNetMessageEncodeHeader;
virNetMessageEncodePayload; virNetMessageEncodePayload;
virNetMessageEncodeNumFDs; virNetMessageEncodeNumFDs;
......
...@@ -2348,7 +2348,7 @@ enum remote_procedure { ...@@ -2348,7 +2348,7 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS = 57, /* skipgen autogen */ REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS = 57, /* skipgen autogen */
REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS = 58, /* autogen autogen */ REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS = 58, /* autogen autogen */
REMOTE_PROC_GET_HOSTNAME = 59, /* autogen autogen priority:high */ 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_PREPARE = 61, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_MIGRATE_PERFORM = 62, /* autogen autogen */ REMOTE_PROC_DOMAIN_MIGRATE_PERFORM = 62, /* autogen autogen */
......
...@@ -298,7 +298,7 @@ elsif ($opt_b) { ...@@ -298,7 +298,7 @@ elsif ($opt_b) {
print "static int ${name}(\n"; print "static int ${name}(\n";
print " virNetServerPtr server,\n"; print " virNetServerPtr server,\n";
print " virNetServerClientPtr client,\n"; print " virNetServerClientPtr client,\n";
print " virNetMessageHeaderPtr hdr,\n"; print " virNetMessagePtr msg,\n";
print " virNetMessageErrorPtr rerr"; print " virNetMessageErrorPtr rerr";
if ($argtype ne "void") { if ($argtype ne "void") {
print ",\n $argtype *args"; print ",\n $argtype *args";
...@@ -315,13 +315,13 @@ elsif ($opt_b) { ...@@ -315,13 +315,13 @@ elsif ($opt_b) {
print "static int ${name}Helper(\n"; print "static int ${name}Helper(\n";
print " virNetServerPtr server,\n"; print " virNetServerPtr server,\n";
print " virNetServerClientPtr client,\n"; print " virNetServerClientPtr client,\n";
print " virNetMessageHeaderPtr hdr,\n"; print " virNetMessagePtr msg,\n";
print " virNetMessageErrorPtr rerr,\n"; print " virNetMessageErrorPtr rerr,\n";
print " void *args$argann,\n"; print " void *args$argann,\n";
print " void *ret$retann)\n"; print " void *ret$retann)\n";
print "{\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 " 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, hdr, rerr"; print " return $name(server, client, msg, rerr";
if ($argtype ne "void") { if ($argtype ne "void") {
print ", args"; print ", args";
} }
...@@ -750,7 +750,7 @@ elsif ($opt_b) { ...@@ -750,7 +750,7 @@ elsif ($opt_b) {
print "static int $name(\n"; print "static int $name(\n";
print " virNetServerPtr server ATTRIBUTE_UNUSED,\n"; print " virNetServerPtr server ATTRIBUTE_UNUSED,\n";
print " virNetServerClientPtr client,\n"; print " virNetServerClientPtr client,\n";
print " virNetMessageHeaderPtr hdr ATTRIBUTE_UNUSED,\n"; print " virNetMessagePtr msg ATTRIBUTE_UNUSED,\n";
print " virNetMessageErrorPtr rerr"; print " virNetMessageErrorPtr rerr";
if ($argtype ne "void") { if ($argtype ne "void") {
print ",\n $argtype *args"; print ",\n $argtype *args";
...@@ -809,7 +809,7 @@ elsif ($opt_b) { ...@@ -809,7 +809,7 @@ elsif ($opt_b) {
print " if (!(st = virStreamNew(priv->conn, VIR_STREAM_NONBLOCK)))\n"; print " if (!(st = virStreamNew(priv->conn, VIR_STREAM_NONBLOCK)))\n";
print " goto cleanup;\n"; print " goto cleanup;\n";
print "\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 " goto cleanup;\n";
print "\n"; print "\n";
} }
......
...@@ -138,7 +138,8 @@ static void virNetServerHandleJob(void *jobOpaque, void *opaque) ...@@ -138,7 +138,8 @@ static void virNetServerHandleJob(void *jobOpaque, void *opaque)
* message types are not expecting replies, so we * message types are not expecting replies, so we
* must just log it & drop them * 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, if (virNetServerProgramUnknownError(job->client,
job->msg, job->msg,
&job->msg->header) < 0) &job->msg->header) < 0)
......
...@@ -770,6 +770,7 @@ readmore: ...@@ -770,6 +770,7 @@ readmore:
/* Grab the completed message */ /* Grab the completed message */
virNetMessagePtr msg = virNetMessageQueueServe(&client->rx); virNetMessagePtr msg = virNetMessageQueueServe(&client->rx);
virNetServerClientFilterPtr filter; virNetServerClientFilterPtr filter;
size_t i;
/* Decode the header so we can use it for routing decisions */ /* Decode the header so we can use it for routing decisions */
if (virNetMessageDecodeHeader(msg) < 0) { if (virNetMessageDecodeHeader(msg) < 0) {
...@@ -778,6 +779,20 @@ readmore: ...@@ -778,6 +779,20 @@ readmore:
return; 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, PROBE(RPC_SERVER_CLIENT_MSG_RX,
"client=%p len=%zu prog=%u vers=%u proc=%u type=%u status=%u serial=%u", "client=%p len=%zu prog=%u vers=%u proc=%u type=%u status=%u serial=%u",
client, msg->bufferLength, client, msg->bufferLength,
...@@ -883,6 +898,15 @@ virNetServerClientDispatchWrite(virNetServerClientPtr client) ...@@ -883,6 +898,15 @@ virNetServerClientDispatchWrite(virNetServerClientPtr client)
if (client->tx->bufferOffset == client->tx->bufferLength) { if (client->tx->bufferOffset == client->tx->bufferLength) {
virNetMessagePtr msg; 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 #if HAVE_SASL
/* Completed this 'tx' operation, so now read for all /* Completed this 'tx' operation, so now read for all
* future rx/tx to be under a SASL SSF layer * future rx/tx to be under a SASL SSF layer
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "memory.h" #include "memory.h"
#include "virterror_internal.h" #include "virterror_internal.h"
#include "logging.h" #include "logging.h"
#include "virfile.h"
#define VIR_FROM_THIS VIR_FROM_RPC #define VIR_FROM_THIS VIR_FROM_RPC
#define virNetError(code, ...) \ #define virNetError(code, ...) \
...@@ -284,6 +285,7 @@ int virNetServerProgramDispatch(virNetServerProgramPtr prog, ...@@ -284,6 +285,7 @@ int virNetServerProgramDispatch(virNetServerProgramPtr prog,
switch (msg->header.type) { switch (msg->header.type) {
case VIR_NET_CALL: case VIR_NET_CALL:
case VIR_NET_CALL_WITH_FDS:
ret = virNetServerProgramDispatchCall(prog, server, client, msg); ret = virNetServerProgramDispatchCall(prog, server, client, msg);
break; break;
...@@ -314,7 +316,8 @@ int virNetServerProgramDispatch(virNetServerProgramPtr prog, ...@@ -314,7 +316,8 @@ int virNetServerProgramDispatch(virNetServerProgramPtr prog,
return ret; return ret;
error: 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); ret = virNetServerProgramSendReplyError(prog, client, msg, &rerr, &msg->header);
} else { } else {
/* Send a dummy reply to free up 'msg' & unblock client rx */ /* Send a dummy reply to free up 'msg' & unblock client rx */
...@@ -355,6 +358,7 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog, ...@@ -355,6 +358,7 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog,
int rv = -1; int rv = -1;
virNetServerProgramProcPtr dispatcher; virNetServerProgramProcPtr dispatcher;
virNetMessageError rerr; virNetMessageError rerr;
size_t i;
memset(&rerr, 0, sizeof(rerr)); memset(&rerr, 0, sizeof(rerr));
...@@ -409,7 +413,20 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog, ...@@ -409,7 +413,20 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog,
* *
* 'args and 'ret' * '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); xdr_free(dispatcher->arg_filter, arg);
...@@ -421,7 +438,7 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog, ...@@ -421,7 +438,7 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog,
/*msg->header.prog = msg->header.prog;*/ /*msg->header.prog = msg->header.prog;*/
/*msg->header.vers = msg->header.vers;*/ /*msg->header.vers = msg->header.vers;*/
/*msg->header.proc = msg->header.proc;*/ /*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.serial = msg->header.serial;*/
msg->header.status = VIR_NET_OK; msg->header.status = VIR_NET_OK;
...@@ -430,6 +447,12 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog, ...@@ -430,6 +447,12 @@ virNetServerProgramDispatchCall(virNetServerProgramPtr prog,
goto error; goto error;
} }
if (msg->nfds &&
virNetMessageEncodeNumFDs(msg) < 0) {
xdr_free(dispatcher->ret_filter, ret);
goto error;
}
if (virNetMessageEncodePayload(msg, dispatcher->ret_filter, ret) < 0) { if (virNetMessageEncodePayload(msg, dispatcher->ret_filter, ret) < 0) {
xdr_free(dispatcher->ret_filter, ret); xdr_free(dispatcher->ret_filter, ret);
goto error; goto error;
......
...@@ -41,7 +41,7 @@ typedef virNetServerProgramProc *virNetServerProgramProcPtr; ...@@ -41,7 +41,7 @@ typedef virNetServerProgramProc *virNetServerProgramProcPtr;
typedef int (*virNetServerProgramDispatchFunc)(virNetServerPtr server, typedef int (*virNetServerProgramDispatchFunc)(virNetServerPtr server,
virNetServerClientPtr client, virNetServerClientPtr client,
virNetMessageHeaderPtr hdr, virNetMessagePtr msg,
virNetMessageErrorPtr rerr, virNetMessageErrorPtr rerr,
void *args, void *args,
void *ret); void *ret);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册