File: dsingleapplication.h

package info (click to toggle)
texstudio 2.3%2Bdebian-3
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 20,992 kB
  • sloc: cpp: 61,734; ansic: 4,300; xml: 726; sh: 125; makefile: 25
file content (185 lines) | stat: -rw-r--r-- 4,941 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*******************************************************************************

  DSingleApplication is basically imitating QtSingleApplication commercial class

  The implementation is though quite different from what is described in
  trolltech documetation for QtSingleApplication. DSingleApplication uses
  tcp sockets to test/open a port in a range and then sed a message to that port
  and expects a correct answer, if it's correct then the app is running and
  we can talk to it.

  Messages sent are in text and start with APP_ID+":", unles message has this three
  bytes it is descarded. Each text message is prepended with int32 value of
  it's size.

  Notes:
  In order to use this class you might consider changing the range of ports to scan
  delimited by: [d_unique_port_start,d_unique_port_finish]
  and timeouts used: d_timeout_try_connect, d_timeout_try_read, d_timeout_try_write.

  Todo:
  Implement another, faster and more robust cross-platform method to identify wheter
  another instance is running, once done then the port scan can be performed.

  Author: Dima Fedorov Levit <dimin@dimin.net> <http://www.dimin.net/>
  Copyright (C) BioImage Informatics <www.bioimage.ucsb.edu>

  Licence: GPL

  History:
    02/08/2007 17:14 - First creation

  ver: 1
*******************************************************************************/

#ifndef D_SINGLE_APPLICATION_H
#define D_SINGLE_APPLICATION_H

const int d_unique_port_start  = 23232;
const int d_unique_port_finish = 23235;

// timeouts are in ms
const int d_timeout_try_connect = 1000;
const int d_timeout_try_read    = 3000;
const int d_timeout_try_write   = 30000;

#include <QString>
#include <QThread>
#include <QTcpSocket>
#include <QTcpServer>

class DTalker;

//******************************************************************************
// DSingleApplication
//******************************************************************************

class DSingleApplication : public QObject {
	Q_OBJECT

public:
	DSingleApplication(const QString & id, bool initialize = true);
	~DSingleApplication();
	QString id() const;
	void initialize();
	bool isRunning() const;

public slots:
	bool sendMessage(const QString & message);

signals:
	void messageReceived(const QString & message);



protected slots:
	void onClientMessage(const QString & message);

private:
	// server is used if no other instance was found to start the port and wait for others
	DTalker *tcpServer;
	// socket is used if other instance was found to communicate with it
	QTcpSocket *tcpSocket;

	int port;
	QString app_id;
	bool other_instance_running;

	void init();
};


//******************************************************************************
// DPortChecker
// This class is used to check specific port if it has an instance of this app
//******************************************************************************

class DPortChecker : public QObject {
	Q_OBJECT

public:
	enum PortStatus { free=0, us=1, others=2 };

	DPortChecker(const QString &id, QObject *parent = 0);
	~DPortChecker();

	PortStatus check(int port);
	QTcpSocket* transferSocketOwnership();

private:
	QTcpSocket *tcpSocket;
	QTcpServer *tcpServer;
	QString app_id;
};


//******************************************************************************
// DTalker
// This is a server responsible to talking to incoming connections
//******************************************************************************

class DTalker : public QTcpServer {
	Q_OBJECT

public:
	DTalker(const QString &id, QObject *parent = 0);

signals:
	void messageReceived(const QString & message);

protected slots:
	void onClientMessage(const QString & message);

protected:
	void incomingConnection(int socketDescriptor);

private:
	QString app_id;

};


//******************************************************************************
// DListner
// This thread is used to communicate with connected client
//******************************************************************************

class DListner : public QThread {
	Q_OBJECT

public:
	DListner(const QString &id, int socketDescriptor, QObject *parent);
	~DListner();

signals:
	void messageReceived(const QString & message);

protected:
	void run();

private:
	int socketDescriptor;
	QString app_id;
	quint32 blockSize;

	void read(QTcpSocket *tcpSocket);
};

//******************************************************************************
// DPortList
//******************************************************************************

class DPortInfo {
public:
	DPortInfo(int p, bool f): port(p), free(f) { }
	int port;
	bool free;
};

class DPortList : public QList<DPortInfo> {
public:
	int firstFreePort();
	bool freePortAvailable();
};

#endif //D_SINGLE_APPLICATION_H