VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/NetworkServiceRunner.cpp@ 79610

Last change on this file since 79610 was 79610, checked in by vboxsync, 5 years ago

Main/IDHCPServer: Added a FindLeaseByMAC method that can be used to query the lease database and help the ValKit finding the TXS running inside a VM it just started using natnet or host-only. This uses a reserved method as it will be backported to 6.0 in a bit. bugref:9288 bugref:9151

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.4 KB
Line 
1/* $Id: NetworkServiceRunner.cpp 79610 2019-07-08 23:29:30Z vboxsync $ */
2/** @file
3 * VirtualBox Main - interface for VBox DHCP server
4 */
5
6/*
7 * Copyright (C) 2009-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <map>
23#include <string>
24#include "NetworkServiceRunner.h"
25
26#include <iprt/process.h>
27#include <iprt/path.h>
28#include <iprt/param.h>
29#include <iprt/env.h>
30#include <iprt/log.h>
31#include <iprt/thread.h>
32
33
34/*********************************************************************************************************************************
35* Global Variables *
36*********************************************************************************************************************************/
37/** @todo Convert to C strings as this is wastefull: */
38const std::string NetworkServiceRunner::kNsrKeyName = "--name";
39const std::string NetworkServiceRunner::kNsrKeyNetwork = "--network";
40const std::string NetworkServiceRunner::kNsrKeyTrunkType = "--trunk-type";
41const std::string NetworkServiceRunner::kNsrTrunkName = "--trunk-name";
42const std::string NetworkServiceRunner::kNsrMacAddress = "--mac-address";
43const std::string NetworkServiceRunner::kNsrIpAddress = "--ip-address";
44const std::string NetworkServiceRunner::kNsrIpNetmask = "--netmask";
45const std::string NetworkServiceRunner::kNsrKeyNeedMain = "--need-main";
46
47
48/*********************************************************************************************************************************
49* Structures and Typedefs *
50*********************************************************************************************************************************/
51struct NetworkServiceRunner::Data
52{
53 Data(const char* aProcName)
54 : mProcName(aProcName)
55 , mProcess(NIL_RTPROCESS)
56 , mKillProcOnStop(false)
57 {}
58 const char *mProcName;
59 RTPROCESS mProcess;
60 std::map<std::string, std::string> mOptions; /**< @todo r=bird: A map for command line option/value pairs? really?
61 * Wouldn't a simple argument list have done it much much more efficiently? */
62 bool mKillProcOnStop;
63};
64
65
66
67NetworkServiceRunner::NetworkServiceRunner(const char *aProcName)
68{
69 m = new NetworkServiceRunner::Data(aProcName);
70}
71
72
73NetworkServiceRunner::~NetworkServiceRunner()
74{
75 stop();
76 delete m;
77 m = NULL;
78}
79
80
81int NetworkServiceRunner::setOption(const std::string& key, const std::string& val)
82{
83 m->mOptions.insert(std::map<std::string, std::string>::value_type(key, val));
84 return VINF_SUCCESS;
85}
86
87
88void NetworkServiceRunner::clearOptions()
89{
90 m->mOptions.clear();
91}
92
93
94void NetworkServiceRunner::detachFromServer()
95{
96 m->mProcess = NIL_RTPROCESS;
97}
98
99
100int NetworkServiceRunner::start(bool aKillProcOnStop)
101{
102 if (isRunning())
103 return VINF_ALREADY_INITIALIZED;
104
105 /*
106 * Construct the path to the executable. ASSUME it is relative to the
107 * directory that holds VBoxSVC.
108 */
109 char szExePath[RTPATH_MAX];
110 AssertReturn(RTProcGetExecutablePath(szExePath, RTPATH_MAX), VERR_FILENAME_TOO_LONG);
111 RTPathStripFilename(szExePath);
112 int vrc = RTPathAppend(szExePath, sizeof(szExePath), m->mProcName);
113 AssertLogRelRCReturn(vrc, vrc);
114
115 /*
116 * Allocate the argument array and construct the argument vector.
117 */
118 size_t const cArgs = 1 + m->mOptions.size() * 2 + 1;
119 char const **papszArgs = (char const **)RTMemTmpAllocZ(sizeof(papszArgs[0]) * cArgs);
120 AssertReturn(papszArgs, VERR_NO_TMP_MEMORY);
121
122 size_t iArg = 0;
123 papszArgs[iArg++] = szExePath;
124 for (std::map<std::string, std::string>::const_iterator it = m->mOptions.begin(); it != m->mOptions.end(); ++it)
125 {
126 papszArgs[iArg++] = it->first.c_str();
127 papszArgs[iArg++] = it->second.c_str();
128 }
129 Assert(iArg + 1 == cArgs);
130 Assert(papszArgs[iArg] == NULL);
131
132 /*
133 * Start the process:
134 */
135 int rc = RTProcCreate(szExePath, papszArgs, RTENV_DEFAULT, 0, &m->mProcess);
136 if (RT_FAILURE(rc))
137 m->mProcess = NIL_RTPROCESS;
138
139 m->mKillProcOnStop = aKillProcOnStop;
140
141 RTMemTmpFree(papszArgs);
142 return rc;
143}
144
145
146int NetworkServiceRunner::stop()
147{
148 /*
149 * If the process already terminated, this function will also grab the exit
150 * status and transition the process out of zombie status.
151 */
152 if (!isRunning())
153 return VINF_OBJECT_DESTROYED;
154
155 bool fDoKillProc = true;
156
157 if (!m->mKillProcOnStop)
158 {
159 /*
160 * This is a VBoxSVC Main client. Do NOT kill it but assume it was shut
161 * down politely. Wait up to 1 second until the process is killed before
162 * doing the final hard kill.
163 */
164 int rc = VINF_SUCCESS;
165 for (unsigned int i = 0; i < 100; i++)
166 {
167 rc = RTProcWait(m->mProcess, RTPROCWAIT_FLAGS_NOBLOCK, NULL);
168 if (RT_SUCCESS(rc))
169 break;
170 RTThreadSleep(10);
171 }
172 if (rc != VERR_PROCESS_RUNNING)
173 fDoKillProc = false;
174 }
175
176 if (fDoKillProc)
177 {
178 RTProcTerminate(m->mProcess);
179 int rc = RTProcWait(m->mProcess, RTPROCWAIT_FLAGS_BLOCK, NULL);
180 NOREF(rc);
181 }
182
183 m->mProcess = NIL_RTPROCESS;
184 return VINF_SUCCESS;
185}
186
187bool NetworkServiceRunner::isRunning()
188{
189 if (m->mProcess == NIL_RTPROCESS)
190 return false;
191
192 RTPROCSTATUS status;
193 int rc = RTProcWait(m->mProcess, RTPROCWAIT_FLAGS_NOBLOCK, &status);
194
195 if (rc == VERR_PROCESS_RUNNING)
196 return true;
197
198 m->mProcess = NIL_RTPROCESS;
199 return false;
200}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette