Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linphone-desktop
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
linphone-desktop
Commits
15b5093b
Commit
15b5093b
authored
Mar 03, 2017
by
Ronan Abhamon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(app): add external `SingleApplication` class
parent
da4d2505
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
670 additions
and
0 deletions
+670
-0
CMakeLists.txt
linphone-desktop/CMakeLists.txt
+3
-0
SingleApplication.cpp
...op/src/externals/single-application/SingleApplication.cpp
+452
-0
SingleApplication.hpp
...op/src/externals/single-application/SingleApplication.hpp
+133
-0
SingleApplicationPrivate.hpp
...externals/single-application/SingleApplicationPrivate.hpp
+82
-0
No files found.
linphone-desktop/CMakeLists.txt
View file @
15b5093b
...
@@ -93,6 +93,7 @@ set(SOURCES
...
@@ -93,6 +93,7 @@ set(SOURCES
src/components/sip-addresses/SipAddressesModel.cpp
src/components/sip-addresses/SipAddressesModel.cpp
src/components/smart-search-bar/SmartSearchBarModel.cpp
src/components/smart-search-bar/SmartSearchBarModel.cpp
src/components/timeline/TimelineModel.cpp
src/components/timeline/TimelineModel.cpp
src/externals/single-application/SingleApplication.cpp
src/main.cpp
src/main.cpp
)
)
...
@@ -123,6 +124,8 @@ set(HEADERS
...
@@ -123,6 +124,8 @@ set(HEADERS
src/components/sip-addresses/SipAddressesModel.hpp
src/components/sip-addresses/SipAddressesModel.hpp
src/components/smart-search-bar/SmartSearchBarModel.hpp
src/components/smart-search-bar/SmartSearchBarModel.hpp
src/components/timeline/TimelineModel.hpp
src/components/timeline/TimelineModel.hpp
src/externals/single-application/SingleApplication.hpp
src/externals/single-application/SingleApplicationPrivate.hpp
src/utils.hpp
src/utils.hpp
)
)
...
...
linphone-desktop/src/externals/single-application/SingleApplication.cpp
0 → 100644
View file @
15b5093b
// The MIT License (MIT)
//
// Copyright (c) Itay Grudev 2015 - 2016
//
// 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.
#include <cstdlib>
#include <QtCore/QDir>
#include <QtCore/QProcess>
#include <QtCore/QByteArray>
#include <QtCore/QSemaphore>
#include <QtCore/QSharedMemory>
#include <QtCore/QStandardPaths>
#include <QtCore/QCryptographicHash>
#include <QtNetwork/QLocalServer>
#include <QtNetwork/QLocalSocket>
#ifdef Q_OS_UNIX
#include <signal.h>
#include <unistd.h>
#endif // ifdef Q_OS_UNIX
#ifdef Q_OS_WIN
#include <windows.h>
#include <lmcons.h>
#endif // ifdef Q_OS_WIN
#include "SingleApplication.hpp"
#include "SingleApplicationPrivate.hpp"
// =============================================================================
static
const
char
NewInstance
=
'N'
;
static
const
char
SecondaryInstance
=
'S'
;
static
const
char
Reconnect
=
'R'
;
static
const
char
InvalidConnection
=
'\0'
;
// -----------------------------------------------------------------------------
SingleApplicationPrivate
::
SingleApplicationPrivate
(
SingleApplication
*
q_ptr
)
:
q_ptr
(
q_ptr
)
{
server
=
nullptr
;
socket
=
nullptr
;
}
SingleApplicationPrivate
::~
SingleApplicationPrivate
()
{
if
(
socket
!=
nullptr
)
{
socket
->
close
();
delete
socket
;
}
memory
->
lock
();
InstancesInfo
*
inst
=
(
InstancesInfo
*
)
memory
->
data
();
if
(
server
!=
nullptr
)
{
server
->
close
();
delete
server
;
inst
->
primary
=
false
;
}
memory
->
unlock
();
delete
memory
;
}
void
SingleApplicationPrivate
::
genBlockServerName
(
int
timeout
)
{
QCryptographicHash
appData
(
QCryptographicHash
::
Sha256
);
appData
.
addData
(
"SingleApplication"
,
17
);
appData
.
addData
(
SingleApplication
::
app_t
::
applicationName
().
toUtf8
());
appData
.
addData
(
SingleApplication
::
app_t
::
organizationName
().
toUtf8
());
appData
.
addData
(
SingleApplication
::
app_t
::
organizationDomain
().
toUtf8
());
if
(
!
(
options
&
SingleApplication
::
Mode
::
ExcludeAppVersion
))
{
appData
.
addData
(
SingleApplication
::
app_t
::
applicationVersion
().
toUtf8
());
}
if
(
!
(
options
&
SingleApplication
::
Mode
::
ExcludeAppPath
))
{
#ifdef Q_OS_WIN
appData
.
addData
(
SingleApplication
::
app_t
::
applicationFilePath
().
toLower
().
toUtf8
());
#else
appData
.
addData
(
SingleApplication
::
app_t
::
applicationFilePath
().
toUtf8
());
#endif // ifdef Q_OS_WIN
}
// User level block requires a user specific data in the hash
if
(
options
&
SingleApplication
::
Mode
::
User
)
{
#ifdef Q_OS_WIN
Q_UNUSED
(
timeout
);
wchar_t
username
[
UNLEN
+
1
];
// Specifies size of the buffer on input
DWORD
usernameLength
=
UNLEN
+
1
;
if
(
GetUserNameW
(
username
,
&
usernameLength
))
{
appData
.
addData
(
QString
::
fromWCharArray
(
username
).
toUtf8
());
}
else
{
appData
.
addData
(
QStandardPaths
::
standardLocations
(
QStandardPaths
::
HomeLocation
).
join
(
""
).
toUtf8
());
}
#endif // ifdef Q_OS_WIN
#ifdef Q_OS_UNIX
QProcess
process
;
process
.
start
(
"whoami"
);
if
(
process
.
waitForFinished
(
timeout
)
&&
process
.
exitCode
()
==
QProcess
::
NormalExit
)
{
appData
.
addData
(
process
.
readLine
());
}
else
{
appData
.
addData
(
QDir
(
QStandardPaths
::
standardLocations
(
QStandardPaths
::
HomeLocation
).
first
()
).
absolutePath
().
toUtf8
()
);
}
#endif // ifdef Q_OS_UNIX
}
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
// server naming requirements.
blockServerName
=
appData
.
result
().
toBase64
().
replace
(
"/"
,
"_"
);
}
void
SingleApplicationPrivate
::
startPrimary
(
bool
resetMemory
)
{
#ifdef Q_OS_UNIX
// Handle any further termination signals to ensure the
// QSharedMemory block is deleted even if the process crashes
crashHandler
();
#endif // ifdef Q_OS_UNIX
// Successful creation means that no main process exists
// So we start a QLocalServer to listen for connections
QLocalServer
::
removeServer
(
blockServerName
);
server
=
new
QLocalServer
();
// Restrict access to the socket according to the
// SingleApplication::Mode::User flag on User level or no restrictions
if
(
options
&
SingleApplication
::
Mode
::
User
)
{
server
->
setSocketOptions
(
QLocalServer
::
UserAccessOption
);
}
else
{
server
->
setSocketOptions
(
QLocalServer
::
WorldAccessOption
);
}
server
->
listen
(
blockServerName
);
QObject
::
connect
(
server
,
&
QLocalServer
::
newConnection
,
this
,
&
SingleApplicationPrivate
::
slotConnectionEstablished
);
// Reset the number of connections
memory
->
lock
();
InstancesInfo
*
inst
=
(
InstancesInfo
*
)
memory
->
data
();
if
(
resetMemory
)
{
inst
->
primary
=
true
;
inst
->
secondary
=
0
;
}
else
{
inst
->
primary
=
true
;
}
memory
->
unlock
();
instanceNumber
=
0
;
}
void
SingleApplicationPrivate
::
startSecondary
()
{
#ifdef Q_OS_UNIX
// Handle any further termination signals to ensure the
// QSharedMemory block is deleted even if the process crashes
crashHandler
();
#endif // ifdef Q_OS_UNIX
}
void
SingleApplicationPrivate
::
connectToPrimary
(
int
msecs
,
char
connectionType
)
{
// Connect to the Local Server of the Primary Instance if not already
// connected.
if
(
socket
==
nullptr
)
{
socket
=
new
QLocalSocket
();
}
// If already connected - we are done;
if
(
socket
->
state
()
==
QLocalSocket
::
ConnectedState
)
return
;
// If not connect
if
(
socket
->
state
()
==
QLocalSocket
::
UnconnectedState
||
socket
->
state
()
==
QLocalSocket
::
ClosingState
)
{
socket
->
connectToServer
(
blockServerName
);
}
// Wait for being connected
if
(
socket
->
state
()
==
QLocalSocket
::
ConnectingState
)
{
socket
->
waitForConnected
(
msecs
);
}
// Initialisation message according to the SingleApplication protocol
if
(
socket
->
state
()
==
QLocalSocket
::
ConnectedState
)
{
// Notify the parent that a new instance had been started;
QByteArray
initMsg
=
blockServerName
.
toLatin1
();
initMsg
.
append
(
connectionType
);
initMsg
.
append
((
const
char
*
)
&
instanceNumber
,
sizeof
(
quint32
));
initMsg
.
append
(
QByteArray
::
number
(
qChecksum
(
initMsg
.
constData
(),
initMsg
.
length
()),
256
));
socket
->
write
(
initMsg
);
socket
->
flush
();
socket
->
waitForBytesWritten
(
msecs
);
}
}
#ifdef Q_OS_UNIX
void
SingleApplicationPrivate
::
crashHandler
()
{
// This guarantees the program will work even with multiple
// instances of SingleApplication in different threads.
// Which in my opinion is idiotic, but lets handle that too.
{
sharedMemMutex
.
lock
();
sharedMem
.
append
(
this
);
sharedMemMutex
.
unlock
();
}
// Handle any further termination signals to ensure the
// QSharedMemory block is deleted even if the process crashes
signal
(
SIGHUP
,
SingleApplicationPrivate
::
terminate
);
// 1
signal
(
SIGINT
,
SingleApplicationPrivate
::
terminate
);
// 2
signal
(
SIGQUIT
,
SingleApplicationPrivate
::
terminate
);
// 3
signal
(
SIGILL
,
SingleApplicationPrivate
::
terminate
);
// 4
signal
(
SIGABRT
,
SingleApplicationPrivate
::
terminate
);
// 6
signal
(
SIGFPE
,
SingleApplicationPrivate
::
terminate
);
// 8
signal
(
SIGBUS
,
SingleApplicationPrivate
::
terminate
);
// 10
signal
(
SIGSEGV
,
SingleApplicationPrivate
::
terminate
);
// 11
signal
(
SIGSYS
,
SingleApplicationPrivate
::
terminate
);
// 12
signal
(
SIGPIPE
,
SingleApplicationPrivate
::
terminate
);
// 13
signal
(
SIGALRM
,
SingleApplicationPrivate
::
terminate
);
// 14
signal
(
SIGTERM
,
SingleApplicationPrivate
::
terminate
);
// 15
signal
(
SIGXCPU
,
SingleApplicationPrivate
::
terminate
);
// 24
signal
(
SIGXFSZ
,
SingleApplicationPrivate
::
terminate
);
// 25
}
void
SingleApplicationPrivate
::
terminate
(
int
signum
)
{
while
(
!
sharedMem
.
empty
())
{
delete
sharedMem
.
back
();
sharedMem
.
pop_back
();
}
::
exit
(
128
+
signum
);
}
QList
<
SingleApplicationPrivate
*>
SingleApplicationPrivate
::
sharedMem
;
QMutex
SingleApplicationPrivate
::
sharedMemMutex
;
#endif // ifdef Q_OS_UNIX
/**
* @brief Executed when a connection has been made to the LocalServer
*/
void
SingleApplicationPrivate
::
slotConnectionEstablished
()
{
Q_Q
(
SingleApplication
);
QLocalSocket
*
nextConnSocket
=
server
->
nextPendingConnection
();
// Verify that the new connection follows the SingleApplication protocol
char
connectionType
=
InvalidConnection
;
quint32
instanceId
;
QByteArray
initMsg
,
tmp
;
if
(
nextConnSocket
->
waitForReadyRead
(
100
))
{
tmp
=
nextConnSocket
->
read
(
blockServerName
.
length
());
// Verify that the socket data start with blockServerName
if
(
tmp
==
blockServerName
.
toLatin1
())
{
initMsg
=
tmp
;
connectionType
=
nextConnSocket
->
read
(
1
)[
0
];
switch
(
connectionType
)
{
case
NewInstance
:
case
SecondaryInstance
:
case
Reconnect
:
{
initMsg
+=
connectionType
;
tmp
=
nextConnSocket
->
read
(
sizeof
(
quint32
));
const
char
*
data
=
tmp
.
constData
();
instanceId
=
(
quint32
)
*
data
;
initMsg
+=
tmp
;
// Verify the checksum of the initMsg
QByteArray
checksum
=
QByteArray
::
number
(
qChecksum
(
initMsg
.
constData
(),
initMsg
.
length
()),
256
);
tmp
=
nextConnSocket
->
read
(
checksum
.
length
());
if
(
checksum
==
tmp
)
break
;
// Otherwise set to invalid connection (next line)
}
default:
connectionType
=
InvalidConnection
;
}
}
}
if
(
connectionType
==
InvalidConnection
)
{
nextConnSocket
->
close
();
delete
nextConnSocket
;
return
;
}
QObject
::
connect
(
nextConnSocket
,
&
QLocalSocket
::
aboutToClose
,
this
,
[
nextConnSocket
,
instanceId
,
this
]()
{
Q_EMIT
this
->
slotClientConnectionClosed
(
nextConnSocket
,
instanceId
);
}
);
QObject
::
connect
(
nextConnSocket
,
&
QLocalSocket
::
readyRead
,
this
,
[
nextConnSocket
,
instanceId
,
this
]()
{
Q_EMIT
this
->
slotDataAvailable
(
nextConnSocket
,
instanceId
);
}
);
if
(
connectionType
==
NewInstance
||
(
connectionType
==
SecondaryInstance
&&
options
&
SingleApplication
::
Mode
::
SecondaryNotification
)
)
{
Q_EMIT
q
->
instanceStarted
();
}
if
(
nextConnSocket
->
bytesAvailable
()
>
0
)
{
Q_EMIT
this
->
slotDataAvailable
(
nextConnSocket
,
instanceId
);
}
}
void
SingleApplicationPrivate
::
slotDataAvailable
(
QLocalSocket
*
dataSocket
,
quint32
instanceId
)
{
Q_Q
(
SingleApplication
);
Q_EMIT
q
->
receivedMessage
(
instanceId
,
dataSocket
->
readAll
());
}
void
SingleApplicationPrivate
::
slotClientConnectionClosed
(
QLocalSocket
*
closedSocket
,
quint32
instanceId
)
{
if
(
closedSocket
->
bytesAvailable
()
>
0
)
Q_EMIT
slotDataAvailable
(
closedSocket
,
instanceId
);
closedSocket
->
deleteLater
();
}
/**
* @brief Constructor. Checks and fires up LocalServer or closes the program
* if another instance already exists
* @param argc
* @param argv
* @param {bool} allowSecondaryInstances
*/
SingleApplication
::
SingleApplication
(
int
&
argc
,
char
*
argv
[],
bool
allowSecondary
,
Options
options
,
int
timeout
)
:
app_t
(
argc
,
argv
),
d_ptr
(
new
SingleApplicationPrivate
(
this
))
{
Q_D
(
SingleApplication
);
// Store the current mode of the program
d
->
options
=
options
;
// Generating an application ID used for identifying the shared memory
// block and QLocalServer
d
->
genBlockServerName
(
timeout
);
// Guarantee thread safe behaviour with a shared memory block. Also by
// explicitly attaching it and then deleting it we make sure that the
// memory is deleted even if the process had crashed on Unix.
#ifdef Q_OS_UNIX
d
->
memory
=
new
QSharedMemory
(
d
->
blockServerName
);
d
->
memory
->
attach
();
delete
d
->
memory
;
#endif // ifdef Q_OS_UNIX
d
->
memory
=
new
QSharedMemory
(
d
->
blockServerName
);
// Create a shared memory block
if
(
d
->
memory
->
create
(
sizeof
(
InstancesInfo
)))
{
d
->
startPrimary
(
true
);
return
;
}
else
{
// Attempt to attach to the memory segment
if
(
d
->
memory
->
attach
())
{
d
->
memory
->
lock
();
InstancesInfo
*
inst
=
(
InstancesInfo
*
)
d
->
memory
->
data
();
if
(
!
inst
->
primary
)
{
d
->
startPrimary
(
false
);
d
->
memory
->
unlock
();
return
;
}
// Check if another instance can be started
if
(
allowSecondary
)
{
inst
->
secondary
+=
1
;
d
->
instanceNumber
=
inst
->
secondary
;
d
->
startSecondary
();
if
(
d
->
options
&
Mode
::
SecondaryNotification
)
{
d
->
connectToPrimary
(
timeout
,
SecondaryInstance
);
}
d
->
memory
->
unlock
();
return
;
}
d
->
memory
->
unlock
();
}
}
d
->
connectToPrimary
(
timeout
,
NewInstance
);
delete
d
;
::
exit
(
EXIT_SUCCESS
);
}
/**
* @brief Destructor
*/
SingleApplication
::~
SingleApplication
()
{
Q_D
(
SingleApplication
);
delete
d
;
}
bool
SingleApplication
::
isPrimary
()
{
Q_D
(
SingleApplication
);
return
d
->
server
!=
nullptr
;
}
bool
SingleApplication
::
isSecondary
()
{
Q_D
(
SingleApplication
);
return
d
->
server
==
nullptr
;
}
quint32
SingleApplication
::
instanceId
()
{
Q_D
(
SingleApplication
);
return
d
->
instanceNumber
;
}
bool
SingleApplication
::
sendMessage
(
QByteArray
message
,
int
timeout
)
{
Q_D
(
SingleApplication
);
// Nobody to connect to
if
(
isPrimary
())
return
false
;
// Make sure the socket is connected
d
->
connectToPrimary
(
timeout
,
Reconnect
);
d
->
socket
->
write
(
message
);
bool
dataWritten
=
d
->
socket
->
flush
();
d
->
socket
->
waitForBytesWritten
(
timeout
);
return
dataWritten
;
}
linphone-desktop/src/externals/single-application/SingleApplication.hpp
0 → 100644
View file @
15b5093b
// The MIT License (MIT)
//
// Copyright (c) Itay Grudev 2015 - 2016
//
// 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.
// See: https://github.com/itay-grudev/SingleApplication/
#ifndef SINGLE_APPLICATION_H
#define SINGLE_APPLICATION_H
#include <QtCore/QtGlobal>
#include <QtNetwork/QLocalSocket>
#ifndef QAPPLICATION_CLASS
#define QAPPLICATION_CLASS QCoreApplication
#endif // ifndef QAPPLICATION_CLASS
#include QT_STRINGIFY(QAPPLICATION_CLASS)
// =============================================================================
class
SingleApplicationPrivate
;
/**
* @brief The SingleApplication class handles multipe instances of the same
* Application
* @see QCoreApplication
*/
class
SingleApplication
:
public
QAPPLICATION_CLASS
{
Q_OBJECT
typedef
QAPPLICATION_CLASS
app_t
;
public:
/**
* @brief Mode of operation of SingleApplication.
* Whether the block should be user-wide or system-wide and whether the
* primary instance should be notified when a secondary instance had been
* started.
* @note Operating system can restrict the shared memory blocks to the same
* user, in which case the User/System modes will have no effect and the
* block will be user wide.
* @enum
*/
enum
Mode
{
User
=
1
<<
0
,
System
=
1
<<
1
,
SecondaryNotification
=
1
<<
2
,
ExcludeAppVersion
=
1
<<
3
,
ExcludeAppPath
=
1
<<
4
};
Q_DECLARE_FLAGS
(
Options
,
Mode
)
/**
* @brief Intitializes a SingleApplication instance with argc command line
* arguments in argv
* @arg {int &} argc - Number of arguments in argv
* @arg {const char *[]} argv - Supplied command line arguments
* @arg {bool} allowSecondary - Whether to start the instance as secondary
* if there is already a primary instance.
* @arg {Mode} mode - Whether for the SingleApplication block to be applied
* User wide or System wide.
* @arg {int} timeout - Timeout to wait in miliseconds.
* @note argc and argv may be changed as Qt removes arguments that it
* recognizes
* @note Mode::SecondaryNotification only works if set on both the primary
* instance and the secondary instance.
* @note The timeout is just a hint for the maximum time of blocking
* operations. It does not guarantee that the SingleApplication
* initialisation will be completed in given time, though is a good hint.
* Usually 4*timeout would be the worst case (fail) scenario.
* @see See the corresponding QAPPLICATION_CLASS constructor for reference
*/
explicit
SingleApplication
(
int
&
argc
,
char
*
argv
[],
bool
allowSecondary
=
false
,
Options
options
=
Mode
::
User
,
int
timeout
=
100
);
~
SingleApplication
();
/**
* @brief Returns if the instance is the primary instance
* @returns {bool}
*/
bool
isPrimary
();
/**
* @brief Returns if the instance is a secondary instance
* @returns {bool}
*/
bool
isSecondary
();
/**
* @brief Returns a unique identifier for the current instance
* @returns {int}
*/
quint32
instanceId
();
/**
* @brief Sends a message to the primary instance. Returns true on success.
* @param {int} timeout - Timeout for connecting
* @returns {bool}
* @note sendMessage() will return false if invoked from the primary
* instance.
*/
bool
sendMessage
(
QByteArray
message
,
int
timeout
=
100
);
Q_SIGNALS:
void
instanceStarted
();
void
receivedMessage
(
quint32
instanceId
,
QByteArray
message
);
private:
SingleApplicationPrivate
*
d_ptr
;
Q_DECLARE_PRIVATE
(
SingleApplication
)
};
Q_DECLARE_OPERATORS_FOR_FLAGS
(
SingleApplication
::
Options
)
#endif // SINGLE_APPLICATION_H
linphone-desktop/src/externals/single-application/SingleApplicationPrivate.hpp
0 → 100644
View file @
15b5093b
// The MIT License (MIT)
//
// Copyright (c) Itay Grudev 2015 - 2016
//
// 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.
//
// W A R N I N G !!!
// -----------------
//
// This file is not part of the SingleApplication API. It is used purely as an
// implementation detail. This header file may change from version to
// version without notice, or may even be removed.
//
#ifndef SINGLE_APPLICATION_PRIVATE_H
#define SINGLE_APPLICATION_PRIVATE_H
#include <QtCore/QMutex>
#include <QtCore/QSharedMemory>
#include <QtNetwork/QLocalServer>
#include <QtNetwork/QLocalSocket>
#include "SingleApplication.hpp"
// =============================================================================
struct
InstancesInfo
{
bool
primary
;
quint32
secondary
;
};
class
SingleApplicationPrivate
:
public
QObject
{
Q_OBJECT
public:
Q_DECLARE_PUBLIC
(
SingleApplication
)
SingleApplicationPrivate
(
SingleApplication
*
q_ptr
);
~
SingleApplicationPrivate
();
void
genBlockServerName
(
int
msecs
);
void
startPrimary
(
bool
resetMemory
);
void
startSecondary
();
void
connectToPrimary
(
int
msecs
,
char
connectionType
);
#ifdef Q_OS_UNIX
void
crashHandler
();
static
void
terminate
(
int
signum
);
static
QList
<
SingleApplicationPrivate
*>
sharedMem
;
static
QMutex
sharedMemMutex
;
#endif // ifdef Q_OS_UNIX
QSharedMemory
*
memory
;
SingleApplication
*
q_ptr
;
QLocalSocket
*
socket
;
QLocalServer
*
server
;
quint32
instanceNumber
;
QString
blockServerName
;
SingleApplication
::
Options
options
;
public
Q_SLOTS
:
void
slotConnectionEstablished
();
void
slotDataAvailable
(
QLocalSocket
*
,
quint32
);
void
slotClientConnectionClosed
(
QLocalSocket
*
,
quint32
);
};
#endif // SINGLE_APPLICATION_PRIVATE_H
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment