]> git.vomp.tv Git - vompclient.git/blob - vdr.cc
Fix for getStringReply to return a difference between an empty
[vompclient.git] / vdr.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "vdr.h"
22
23 VDR* VDR::instance = NULL;
24
25 VDR::VDR()
26 {
27   if (instance) return;
28   instance = this;
29   initted = 0;
30   findingServer = 0;
31   tcp = NULL;
32   pthread_mutex_init(&mutex, NULL);
33 }
34
35 VDR::~VDR()
36 {
37   instance = NULL;
38   if (initted) shutdown();
39 }
40
41 VDR* VDR::getInstance()
42 {
43   return instance;
44 }
45
46 int VDR::init(int tport)
47 {
48   if (initted) return 0;
49   initted = 1;
50   port = tport;
51   logger = Log::getInstance();
52   return 1;
53 }
54
55 int VDR::shutdown()
56 {
57   if (!initted) return 0;
58   initted = 0;
59   disconnect();
60   return 1;
61 }
62
63 void VDR::findServers(std::vector<char*>& serverIPs)
64 {
65   findingServer = 1;
66   char* message = "VOMP CLIENT";
67   DatagramSocket ds(port);
68
69   int haveAtLeastOne = 0;
70   char* newIP;
71   int retval;
72   int waitType = 1;
73   while(findingServer)
74   {
75     if (waitType == 1)
76     {
77       logger->log("VDR", Log::NOTICE, "Broadcasting for server");
78       ds.send("255.255.255.255", 3024, message, strlen(message));
79     }
80     retval = ds.waitforMessage(waitType);
81
82     if (retval == 2) // we got a reply
83     {
84       if (strcmp(ds.getData(), "VOMP SERVER")) // echo.....
85       {
86         waitType = 2;
87       }
88       else
89       {
90         newIP = new char[16];
91         strcpy(newIP, ds.getFromIPA());
92         serverIPs.push_back(newIP);
93         waitType = 2;
94         haveAtLeastOne = 1;
95       }
96     }
97     else
98     {
99       if (haveAtLeastOne) break;
100       waitType = 1;
101     }
102   }
103 }
104
105 void VDR::cancelFindingServer()
106 {
107   findingServer = 0;
108 }
109
110 void VDR::setServerIP(char* newIP)
111 {
112   strcpy(serverIP, newIP);
113 }
114
115 int VDR::connect()
116 {
117   if (tcp) delete tcp;
118   tcp = new TCP();
119   return tcp->connectTo(serverIP, 3024);
120 }
121
122 void VDR::disconnect()
123 {
124   if (tcp) delete tcp;
125   tcp = NULL;
126   Log::getInstance()->log("VDR", Log::DEBUG, "Disconnect");
127 }
128
129 long VDR::getSimpleReply()
130 {
131   unsigned char* p = (unsigned char*)tcp->receivePacket();
132   if (!p) return -1;
133
134   Log::getInstance()->log("VDR", Log::DEBUG, "tcp data length = %i", tcp->getDataLength());
135
136   if (tcp->getDataLength() != 4)
137   {
138     free(p);
139     return -1;
140   }
141
142   ULONG reply = ntohl(*(ULONG*)p);
143
144   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said %li", reply);
145
146   free(p);
147
148   return reply;
149 }
150
151 char* VDR::getStringReply()
152 {
153   unsigned char* p = (unsigned char*)tcp->receivePacket();
154   if (!p) return NULL;
155
156   int dataLength = tcp->getDataLength();
157
158 //  Log::getInstance()->log("VDR", Log::DEBUG, "GSR Data length %u", dataLength);
159
160   if ((dataLength == 4) && (p[0] == '\0'))
161   {
162     Log::getInstance()->log("VDR", Log::DEBUG, "GSR returning null no string returned");
163     free(p);
164     return NULL; // no string returned
165   }
166
167   char* returnText;
168   int tLength;
169
170   tLength = strlen((char*)p);
171   returnText = new char[tLength + 1];
172   strcpy(returnText, (char*)p);
173
174   free(p);
175
176   return returnText;
177 }
178
179 /////////////////////////////////////////////////////////////////////////////
180
181 int VDR::doLogin()
182 {
183   UCHAR buffer[8];
184
185   *(unsigned long*)&buffer[0] = htonl(4);
186   *(unsigned long*)&buffer[4] = htonl(VDR_LOGIN);
187
188   pthread_mutex_lock(&mutex);
189   int a = tcp->sendPacket(buffer, 8);
190   if (a != 8)
191   {
192     pthread_mutex_unlock(&mutex);
193     return 0;
194   }
195
196   // reply
197
198   UCHAR* p = tcp->receivePacket();
199   pthread_mutex_unlock(&mutex);
200   if (!p) return 0;
201
202   int count = 0;
203
204   unsigned long vdrTime = ntohl(*(unsigned long*)&p[count]);
205   count += sizeof(unsigned long);
206   Log::getInstance()->log("VDR", Log::DEBUG, "vdrtime = %lu", vdrTime);
207
208   struct timespec currentTime;
209   currentTime.tv_sec = vdrTime;
210   currentTime.tv_nsec = 0;
211   int b = clock_settime(CLOCK_REALTIME, &currentTime);
212
213   Log::getInstance()->log("VDR", Log::DEBUG, "set clock = %u", b);
214
215   // now make a TZ variable and set it
216   signed int vdrTimeOffset = ntohl(*(signed int*)&p[count]);
217   Log::getInstance()->log("VDR", Log::DEBUG, "offset = %i", vdrTimeOffset);
218
219   char sign;
220   int hours;
221   int minutes;
222   if (vdrTimeOffset > 0) sign = '-';
223   else sign = '+';
224
225   vdrTimeOffset = abs(vdrTimeOffset);
226
227   hours = (int)vdrTimeOffset / 3600;
228   minutes = vdrTimeOffset % 3600;
229
230   Log::getInstance()->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
231
232   minutes = (int)minutes / 60;
233
234   Log::getInstance()->log("VDR", Log::DEBUG, "%c %i %i", sign, hours, minutes);
235
236   char newTZ[30];
237   sprintf(newTZ, "MVP%c%i:%i", sign, hours, minutes);
238   setenv("TZ", newTZ, 1);
239
240   Log::getInstance()->log("VDR", Log::DEBUG, "Timezone data: %s", newTZ);
241
242   free(p);
243   return 1;
244 }
245
246 Directory* VDR::getRecordingsList()
247 {
248   UCHAR buffer[8];
249
250   *(unsigned long*)&buffer[0] = htonl(4);
251   *(unsigned long*)&buffer[4] = htonl(VDR_GETRECORDINGLIST);
252
253   pthread_mutex_lock(&mutex);
254   int a = tcp->sendPacket(buffer, 8);
255   if (a != 8)
256   {
257     pthread_mutex_unlock(&mutex);
258     return NULL;
259   }
260
261   // reply
262
263   unsigned char* p = (unsigned char*)tcp->receivePacket();
264   pthread_mutex_unlock(&mutex);
265   if (!p) return 0;
266
267   Directory* recDir = new Directory();
268   recDir->setName("/");
269   recDir->isRoot = 1;
270
271   int dataLength = tcp->getDataLength();
272
273   Log::getInstance()->log("VDR", Log::DEBUG, "Data length %u", dataLength);
274
275   int count = 0;
276
277   Directory::totalSpace = (*(ULONG*)&p[count]);
278   count += sizeof(ULONG);
279   Directory::freeSpace = (*(ULONG*)&p[count]);
280   count += sizeof(ULONG);
281   Directory::usedPercent = (*(ULONG*)&p[count]);
282   count += sizeof(ULONG);
283
284   int tLength;
285
286   while (count < dataLength)
287   {
288     Recording* rec = new Recording();
289     rec->start = ntohl(*(unsigned long*)&p[count]);
290     count += 4;
291
292     tLength = strlen((char*)&p[count]);
293     rec->setName((char*)&p[count]);
294
295 //    rec->name = new char[tLength + 1];
296 //    strcpy(rec->name, (char*)&p[count]);
297     count += tLength + 1;
298
299     tLength = strlen((char*)&p[count]);
300     rec->fileName = new char[tLength + 1];
301     strcpy(rec->fileName, (char*)&p[count]);
302     count += tLength + 1;
303
304     if(rec->isInDir())
305     {
306       char* dirName = rec->getDirName();
307
308       Directory* d = recDir->getDirByName(dirName);
309       if (!d)
310       {
311         d = new Directory();
312         d->setName(dirName);
313         Log::getInstance()->log("VDR", Log::DEBUG, "Added a new directory = %s", d->name);
314         recDir->dirList->add(d);
315       }
316
317       d->recList->add(rec);
318       d->recList->next();
319     }
320     else
321     {
322       recDir->recList->add(rec);
323       recDir->recList->next();
324     }
325
326     Log::getInstance()->log("VDR", Log::DEBUG, "Have added a recording to list. %lu %s", rec->start, rec->getProgName());
327   }
328
329   free(p);
330
331   return recDir;
332 }
333
334 int VDR::deleteRecording(char* fileName)
335 {
336   unsigned long totalLength = 8 + strlen(fileName) + 1;
337   UCHAR buffer[totalLength];
338
339   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
340   *(unsigned long*)&buffer[4] = htonl(VDR_DELETERECORDING);
341   strcpy((char*)&buffer[8], fileName);
342
343   pthread_mutex_lock(&mutex);
344   unsigned int a = tcp->sendPacket(buffer, totalLength);
345   if (a != totalLength)
346   {
347     pthread_mutex_unlock(&mutex);
348     return 0;
349   }
350
351   int toReturn = getSimpleReply();
352   pthread_mutex_unlock(&mutex);
353   return toReturn;
354 }
355
356 char* VDR::getRecordingSummary(char* fileName)
357 {
358   unsigned long totalLength = 8 + strlen(fileName) + 1;
359   UCHAR buffer[totalLength];
360
361   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
362   *(unsigned long*)&buffer[4] = htonl(VDR_GETSUMMARY);
363   strcpy((char*)&buffer[8], fileName);
364
365   pthread_mutex_lock(&mutex);
366   unsigned int a = tcp->sendPacket(buffer, totalLength);
367   if (a != totalLength)
368   {
369     pthread_mutex_unlock(&mutex);
370     return NULL;
371   }
372
373   char* toReturn = getStringReply();
374   pthread_mutex_unlock(&mutex);
375   return toReturn;
376 }
377
378 List* VDR::getChannelsList(ULONG type)
379 {
380   UCHAR buffer[8];
381
382   *(unsigned long*)&buffer[0] = htonl(4);
383   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELLIST);
384
385   pthread_mutex_lock(&mutex);
386   int a = tcp->sendPacket(buffer, 8);
387   if (a != 8)
388   {
389     pthread_mutex_unlock(&mutex);
390     return NULL;
391   }
392
393   // reply
394
395   unsigned char* p = (unsigned char*)tcp->receivePacket();
396   pthread_mutex_unlock(&mutex);
397   if (!p) return NULL;
398
399   List* chanList = new List();
400
401   int dataLength = tcp->getDataLength();
402
403   Log::getInstance()->log("VDR", Log::DEBUG, "Data length %u", dataLength);
404
405   int count = 0;
406
407   int tLength;
408
409   while (count < dataLength)
410   {
411     Channel* chan = new Channel();
412     chan->number = ntohl(*(unsigned long*)&p[count]);
413     count += 4;
414     chan->type = ntohl(*(unsigned long*)&p[count]);
415     count += 4;
416
417     tLength = strlen((char*)&p[count]);
418     chan->name = new char[tLength + 1];
419     strcpy(chan->name, (char*)&p[count]);
420     count += tLength + 1;
421
422     if (chan->type == type)
423     {
424       chanList->add(chan);
425       chanList->next();
426       Log::getInstance()->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
427     }
428     else
429     {
430       delete chan;
431     }
432   }
433
434   free(p);
435
436   return chanList;
437 }
438
439 int VDR::streamChannel(ULONG number)
440 {
441   UCHAR buffer[12];
442
443   *(unsigned long*)&buffer[0] = htonl(8);
444   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMCHANNEL);
445   *(unsigned long*)&buffer[8] = htonl(number);
446
447   pthread_mutex_lock(&mutex);
448   int a = tcp->sendPacket(buffer, 12);
449
450   if (a != 12)
451   {
452     pthread_mutex_unlock(&mutex);
453     return 0;
454   }
455
456   int toReturn = getSimpleReply();
457   pthread_mutex_unlock(&mutex);
458   return toReturn;
459 }
460
461 int VDR::stopStreaming()
462 {
463   UCHAR buffer[8];
464
465   *(unsigned long*)&buffer[0] = htonl(4);
466   *(unsigned long*)&buffer[4] = htonl(VDR_STOPSTREAMING);
467
468   pthread_mutex_lock(&mutex);
469   int a = tcp->sendPacket(buffer, 8);
470
471   if (a != 8)
472   {
473     pthread_mutex_unlock(&mutex);
474     return 0;
475   }
476
477   int toReturn = getSimpleReply();
478   pthread_mutex_unlock(&mutex);
479   return toReturn;
480 }
481
482 UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived)
483 {
484   UCHAR buffer[20];
485
486   *(unsigned long*)&buffer[0] = htonl(16);
487   *(unsigned long*)&buffer[4] = htonl(VDR_GETBLOCK);
488   *(ULLONG*)&buffer[8]        = htonll(position);
489   *(unsigned long*)&buffer[16] = htonl(maxAmount);
490
491   pthread_mutex_lock(&mutex);
492   int a = tcp->sendPacket(buffer, 20);
493   if (a != 20)
494   {
495     pthread_mutex_unlock(&mutex);
496     return NULL;
497   }
498
499   unsigned char* p = (unsigned char*)tcp->receivePacket();
500   pthread_mutex_unlock(&mutex);
501   if (!p) return NULL;
502   *amountReceived = tcp->getDataLength();
503   return p;
504 }
505
506 ULLONG VDR::streamRecording(Recording* rec)
507 {
508   unsigned long totalLength = 8 + strlen(rec->fileName) + 1;
509   UCHAR buffer[totalLength];
510
511   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
512   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMRECORDING);
513   strcpy((char*)&buffer[8], rec->fileName);
514
515   pthread_mutex_lock(&mutex);
516   unsigned int a = tcp->sendPacket(buffer, totalLength);
517   if (a != totalLength)
518   {
519     pthread_mutex_unlock(&mutex);
520     return 0;
521   }
522
523   unsigned char* p = (unsigned char*)tcp->receivePacket();
524   pthread_mutex_unlock(&mutex);
525   if (!p) return 0;
526
527   if (tcp->getDataLength() != 8)
528   {
529     free(p);
530     return 0;
531   }
532
533   ULLONG recordingLength = ntohll(*(ULLONG*)p);
534
535   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
536   free(p);
537
538   return recordingLength;
539 }
540
541 ULLONG VDR::rescanRecording()
542 {
543   unsigned long totalLength = 8;
544   UCHAR buffer[totalLength];
545
546   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
547   *(unsigned long*)&buffer[4] = htonl(VDR_RESCANRECORDING);
548
549   pthread_mutex_lock(&mutex);
550   unsigned int a = tcp->sendPacket(buffer, totalLength);
551   if (a != totalLength)
552   {
553     pthread_mutex_unlock(&mutex);
554     return 0;
555   }
556
557   unsigned char* p = (unsigned char*)tcp->receivePacket();
558   pthread_mutex_unlock(&mutex);
559   if (!p) return 0;
560
561   if (tcp->getDataLength() != 8)
562   {
563     free(p);
564     return 0;
565   }
566
567   ULLONG recordingLength = ntohll(*(ULLONG*)p);
568
569   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
570   free(p);
571
572   return recordingLength;
573 }
574
575 int VDR::getChannelSchedule(ULONG number)
576 {
577   UCHAR buffer[12];
578
579   *(unsigned long*)&buffer[0] = htonl(8);
580   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELSCHEDULE);
581   *(unsigned long*)&buffer[8] = htonl(number);
582
583   pthread_mutex_lock(&mutex);
584   int a = tcp->sendPacket(buffer, 12);
585
586   if (a != 12)
587   {
588     pthread_mutex_unlock(&mutex);
589     return -1;
590   }
591
592   unsigned char* p = (unsigned char*)tcp->receivePacket();
593   pthread_mutex_unlock(&mutex);
594   if (!p) return -1;
595
596   int dataLength = tcp->getDataLength();
597
598   if (dataLength != 4)
599   {
600     free(p);
601     return -1;
602   }
603
604   ULONG data = ntohl(*(ULONG*)p);
605   free(p);
606
607   Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule %lu", data);
608
609   return data;
610 }
611
612 ULLONG VDR::getResumePoint(char* fileName)
613 {
614   char* resumeString = configLoad("ResumeData", fileName);
615   if (!resumeString) return 0;
616
617   ULLONG toReturn = strtoull(resumeString, NULL, 10);
618   delete[] resumeString;
619   return toReturn;
620 }
621
622 int VDR::configSave(char* section, char* key, char* value)
623 {
624   ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls
625   UCHAR buffer[totalLength];
626
627   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
628   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGSAVE);
629
630   int position = 8;
631   strcpy((char*)&buffer[position], section);
632   position += strlen(section) + 1;
633   strcpy((char*)&buffer[position], key);
634   position += strlen(key) + 1;
635   strcpy((char*)&buffer[position], value);
636
637   pthread_mutex_lock(&mutex);
638   unsigned int a = tcp->sendPacket(buffer, totalLength);
639   if (a != totalLength)
640   {
641     pthread_mutex_unlock(&mutex);
642     return 0;
643   }
644
645   int toReturn = getSimpleReply();
646   pthread_mutex_unlock(&mutex);
647   return toReturn;
648 }
649
650 char* VDR::configLoad(char* section, char* key)
651 {
652   ULONG totalLength = 8 + strlen(section) + strlen(key) + 2; // 8 for headers, 2 for nulls
653   UCHAR buffer[totalLength];
654
655   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
656   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGLOAD);
657
658   int position = 8;
659   strcpy((char*)&buffer[position], section);
660   position += strlen(section) + 1;
661   strcpy((char*)&buffer[position], key);
662
663   pthread_mutex_lock(&mutex);
664   unsigned int a = tcp->sendPacket(buffer, totalLength);
665   if (a != totalLength)
666   {
667     pthread_mutex_unlock(&mutex);
668     return NULL;
669   }
670
671   char* toReturn = getStringReply();
672   pthread_mutex_unlock(&mutex);
673   return toReturn;
674 }