Sync with 5.2.0
[deliverable/titan.core.git] / common / usage_stats.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "usage_stats.hh"
9
10 #ifdef MINGW
11 # include <windows.h>
12 # include <lmcons.h>
13 #else
14 # include <pwd.h>
15 #endif
16
17 #include <arpa/inet.h>
18 #include <assert.h>
19 #include <errno.h>
20 #include <netinet/in.h>
21 #include <signal.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/wait.h>
28 #include <netdb.h>
29 #include <unistd.h>
30 #include <sys/utsname.h>
31 #include <stdio.h>
32 #include <time.h>
33
34 #define SA struct sockaddr
35 #define MAXLINE 4096
36 #define MAXSUB 2000
37
38 #define LISTENQ 1024
39
40 std::string UsageData::id;
41 std::string UsageData::host;
42 std::string UsageData::platform;
43
44 #ifdef sun
45 extern int gethostname( char *name, int namelen );
46 #endif
47
48 static int countDots (const char *name )
49 {
50 int n;
51 for (n=0; *name; ++name) if (*name=='.') ++n;
52 return(n);
53 }
54
55 std::string gethostnameFullyQualified ( void )
56 {
57 char host[774];
58 struct hostent *hp;
59 char *fqname=NULL;
60 int nd;
61 host[0] = 0;
62
63 if (-1 == gethostname(host, sizeof(host))) {
64 //perror("warning - getting local hostname");
65 strcpy(host,"localhost");
66 }
67 fqname = host;
68 nd = countDots(fqname);
69
70 hp = gethostbyname(host);
71 if (!hp) {
72 //fprintf(stderr, "warning - can't gethostbyname(%s): %s\n",host, hstrerror(h_errno));
73 }
74 else {
75 char **nm;
76 if (nd <= countDots(hp->h_name)) {
77 fqname = const_cast<char*>(hp->h_name);
78 nd = countDots(fqname);
79 }
80
81 for (nm = hp->h_aliases; *nm; ++nm) {
82 int d = countDots(*nm);
83 if (d > nd) {fqname = *nm; nd=d;}
84 }
85 }
86
87 if (2 > nd) {
88 /* still need to find a domain, look through the usual suspects:
89 * LOCALDOMAIN env variable
90 * domain defn from /etc/resolv.conf
91 * /etc/defaultdomain (sun only?)
92 */
93 FILE *fp = NULL;
94 char domain[1024];
95 char *e = getenv("LOCALDOMAIN");
96 if (e) strcpy(domain, e);
97 else domain[0] = 0;
98
99 if( !domain[0] && NULL != (fp=fopen("/etc/resolv.conf","r")) ) {
100 nd = 0;
101 while( fgets(domain, sizeof(domain), fp) ) {
102 if( 0==strncmp("domain ",domain,7) ) {
103 nd = strlen(domain) - 7;
104 memmove(domain, domain+7, nd);
105 }
106 }
107 domain[nd] = 0; /* nul terminate (or reset empty) */
108 fclose(fp);
109 }
110
111 if( !domain[0] && NULL != (fp=fopen("/etc/defaultdomain","r")) ) {
112 fgets(domain, sizeof(domain), fp);
113 fclose(fp);
114 }
115
116 if( domain[0] ) {
117 /* trim blanks */
118 int first = 0;
119 nd = strlen(domain) - 1;
120 while (first <= nd && isspace(domain[first])) ++first;
121 while (nd > first && isspace(domain[nd])) domain[nd--] = 0;
122
123 if (domain[first]) {
124 if (fqname != host) strcpy(host,fqname);
125 if ('.'!=domain[first]) strcat(host,".");
126 strcat(host,domain+first);
127 fqname = host;
128 }
129 }
130 }
131 return(std::string(fqname));
132 }
133
134 UsageData::UsageData() {
135
136 #ifdef MINGW
137 TCHAR user_name[UNLEN + 1], computer_name[MAX_COMPUTERNAME_LENGTH + 1];
138 DWORD buffer_size = sizeof(user_name);
139 if (GetUserName(user_name, &buffer_size)) id=user_name;
140 else id="unknown";
141
142 buffer_size = sizeof(computer_name);
143 if (GetComputerName(computer_name, &buffer_size))
144 host=computer_name;
145 else host="unknown";
146 #else
147 struct passwd *p;
148 setpwent();
149 p = getpwuid(getuid());
150 if (p != NULL)
151 id = p->pw_name;
152 else
153 id="unknown";
154 endpwent();
155
156 host = gethostnameFullyQualified();
157
158 struct utsname name;
159
160 int result = uname(&name);
161 if (result >= 0)
162 platform= std::string(name.sysname) + " " + std::string(name.release) + " " + std::string(name.machine);
163 else
164 platform="unknown";
165
166 #ifdef LINUX
167 std::string dist;
168 FILE *fp;
169 char path[128];
170
171 fp = popen("lsb_release -a 2>/dev/null", "r");
172 if (fp != NULL) {
173 while (fgets(path, sizeof(path), fp) != NULL)
174 if (strncmp ("Description",path,11) == 0) dist.append(path);
175 //printf("\n'%s'\n", dist.c_str());
176 pclose(fp);
177 }
178 dist.erase(0,12);
179 platform.append(dist);
180 #endif
181
182 #endif
183 }
184
185 UsageData::~UsageData() {
186
187 }
188
189 struct thread_data {
190 std::string msg;
191 Sender* sndr;
192 };
193
194 void UsageData::sendDataThreaded(std::string msg, Sender* sender) {
195 thread_data* data = new thread_data; // will be deleted by sendData
196 data->msg = "id="+ id + "&host=" + host + "&platform=" + platform + "&gccv=" + C_COMPILER_VERSION + "&titanv=" + PRODUCT_NUMBER + "&msg="+ msg + "\r";
197 data->sndr = sender;
198
199 pthread_t thread;
200 pthread_create(&thread, NULL, sendData, data);
201 }
202
203 void* UsageData::sendData(void* m) {
204 thread_data* my_data;
205 my_data = (thread_data*)m;
206
207 if(my_data->sndr) {
208 my_data->sndr->send(my_data->msg.c_str());
209 delete my_data->sndr;
210 }
211
212 // delete the data after use
213 delete my_data;
214
215 return NULL;
216 }
217
218
219 //**************** HttpSender *******************
220
221 ssize_t process_http(int sockfd, const char *host, const char *page, const char *poststr)
222 {
223 char sendline[MAXLINE + 1];//, recvline[MAXLINE + 1];
224 ssize_t n = 0;
225 //printf("\n ##### \n%s\n ##### \n", poststr);
226 snprintf(sendline, MAXSUB,
227 "POST %s HTTP/1.0\r\n"
228 "Host: %s\r\n"
229 "Content-type: application/x-www-form-urlencoded\r\n"
230 "Content-length: %lu\r\n\r\n"
231 "%s", page, host, (unsigned long)strlen(poststr), poststr);
232
233 write(sockfd, sendline, strlen(sendline));
234 /*while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
235 recvline[n] = '\0';
236 printf("%s", recvline);
237 }*/
238 return n;
239 }
240
241 // msg must be in the right format to process!
242 // id=x&host=y&platform=z&gccv=v&titanv=t&msg=m\r
243 void HttpSender::send(const char* msg) {
244 int sockfd;
245 struct sockaddr_in servaddr, clientaddr;
246
247 char **pptr;
248 const char *hname = "ttcn.ericsson.se";
249 const char *page = "/download/usage_stats/usage_stats.php";
250 const char *poststr = msg;//.c_str();
251 //*******************************************************
252
253 char str[50];
254 struct hostent *hptr;
255 if ((hptr = gethostbyname(hname)) == NULL) {
256 /*fprintf(stderr, " gethostbyname error for host: %s: %s",
257 hname, hstrerror(h_errno));*/
258 return;
259 }
260 //printf("hostname: %s\n", hptr->h_name);
261 if (hptr->h_addrtype == AF_INET
262 && (pptr = hptr->h_addr_list) != NULL) {
263 //printf("address: %s\n",
264 inet_ntop(hptr->h_addrtype, *pptr, str,sizeof(str));
265 } else {
266 //fprintf(stderr, "Error call inet_ntop \n");
267 return;
268 }
269
270 sockfd = socket(AF_INET, SOCK_STREAM, 0);
271
272 memset(&clientaddr, 0, sizeof(clientaddr));
273 clientaddr.sin_family = AF_INET;
274 clientaddr.sin_port = htons(49555);
275 inet_pton(AF_INET, "0.0.0.0", &clientaddr.sin_addr);
276 if (bind(sockfd, (SA *) & clientaddr, sizeof(clientaddr)) < 0) {
277 clientaddr.sin_port = htons(59555);
278 if (bind(sockfd, (SA *) & clientaddr, sizeof(clientaddr)) < 0) {
279 clientaddr.sin_port = htons(61555);
280 if (bind(sockfd, (SA *) & clientaddr, sizeof(clientaddr)) < 0) {
281 // last ditch effort, use an automatically generated port
282 clientaddr.sin_port = htons(0);
283 bind(sockfd, (SA *) & clientaddr, sizeof(clientaddr));
284 }
285 }
286 }
287
288 memset(&servaddr, 0, sizeof(servaddr));
289 servaddr.sin_family = AF_INET;
290 servaddr.sin_port = htons(80);
291 inet_pton(AF_INET, str, &servaddr.sin_addr);
292
293 connect(sockfd, (SA *) & servaddr, sizeof(servaddr));
294
295 process_http(sockfd, hname, page, poststr);
296 close(sockfd);
297 }
298
299 //**************** DNSSender *******************
300
301 DNSSender::DNSSender() : nameserver("172.31.21.9"), domain("domain.net") { }
302
303 void DNSSender::send(const char* /* msg */) {
304 //send_over_dns(msg, "TXT", "pass", nameserver, domain);
305 }
306
This page took 0.074525 seconds and 5 git commands to generate.