]> git.vomp.tv Git - vompclient.git/blob - vdr.cc
Fix for negatives in getSimpleReply
[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   if (toReturn == -1) toReturn = 0; // error is same as 0=bad in this case
353   pthread_mutex_unlock(&mutex);
354   return toReturn;
355 }
356
357 char* VDR::getRecordingSummary(char* fileName)
358 {
359   unsigned long totalLength = 8 + strlen(fileName) + 1;
360   UCHAR buffer[totalLength];
361
362   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
363   *(unsigned long*)&buffer[4] = htonl(VDR_GETSUMMARY);
364   strcpy((char*)&buffer[8], fileName);
365
366   pthread_mutex_lock(&mutex);
367   unsigned int a = tcp->sendPacket(buffer, totalLength);
368   if (a != totalLength)
369   {
370     pthread_mutex_unlock(&mutex);
371     return NULL;
372   }
373
374   char* toReturn = getStringReply();
375   pthread_mutex_unlock(&mutex);
376   return toReturn;
377 }
378
379 List* VDR::getChannelsList(ULONG type)
380 {
381   UCHAR buffer[8];
382
383   *(unsigned long*)&buffer[0] = htonl(4);
384   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELLIST);
385
386   pthread_mutex_lock(&mutex);
387   int a = tcp->sendPacket(buffer, 8);
388   if (a != 8)
389   {
390     pthread_mutex_unlock(&mutex);
391     return NULL;
392   }
393
394   // reply
395
396   unsigned char* p = (unsigned char*)tcp->receivePacket();
397   pthread_mutex_unlock(&mutex);
398   if (!p) return NULL;
399
400   List* chanList = new List();
401
402   int dataLength = tcp->getDataLength();
403
404   Log::getInstance()->log("VDR", Log::DEBUG, "Data length %u", dataLength);
405
406   int count = 0;
407
408   int tLength;
409
410   while (count < dataLength)
411   {
412     Channel* chan = new Channel();
413     chan->number = ntohl(*(unsigned long*)&p[count]);
414     count += 4;
415     chan->type = ntohl(*(unsigned long*)&p[count]);
416     count += 4;
417
418     tLength = strlen((char*)&p[count]);
419     chan->name = new char[tLength + 1];
420     strcpy(chan->name, (char*)&p[count]);
421     count += tLength + 1;
422
423     if (chan->type == type)
424     {
425       chanList->add(chan);
426       chanList->next();
427       Log::getInstance()->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
428     }
429     else
430     {
431       delete chan;
432     }
433   }
434
435   free(p);
436
437   return chanList;
438 }
439
440 int VDR::streamChannel(ULONG number)
441 {
442   UCHAR buffer[12];
443
444   *(unsigned long*)&buffer[0] = htonl(8);
445   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMCHANNEL);
446   *(unsigned long*)&buffer[8] = htonl(number);
447
448   pthread_mutex_lock(&mutex);
449   int a = tcp->sendPacket(buffer, 12);
450
451   if (a != 12)
452   {
453     pthread_mutex_unlock(&mutex);
454     return 0;
455   }
456
457   int toReturn = getSimpleReply();
458   if (toReturn == -1) toReturn = 0; // change error to bad
459   pthread_mutex_unlock(&mutex);
460   return toReturn;
461 }
462
463 int VDR::stopStreaming()
464 {
465   UCHAR buffer[8];
466
467   *(unsigned long*)&buffer[0] = htonl(4);
468   *(unsigned long*)&buffer[4] = htonl(VDR_STOPSTREAMING);
469
470   pthread_mutex_lock(&mutex);
471   int a = tcp->sendPacket(buffer, 8);
472
473   if (a != 8)
474   {
475     pthread_mutex_unlock(&mutex);
476     return 0;
477   }
478
479   int toReturn = getSimpleReply();
480   if (toReturn == -1) toReturn = 0; // change error to bad
481   pthread_mutex_unlock(&mutex);
482   return toReturn;
483 }
484
485 UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived)
486 {
487   UCHAR buffer[20];
488
489   *(unsigned long*)&buffer[0] = htonl(16);
490   *(unsigned long*)&buffer[4] = htonl(VDR_GETBLOCK);
491   *(ULLONG*)&buffer[8]        = htonll(position);
492   *(unsigned long*)&buffer[16] = htonl(maxAmount);
493
494   pthread_mutex_lock(&mutex);
495   int a = tcp->sendPacket(buffer, 20);
496   if (a != 20)
497   {
498     pthread_mutex_unlock(&mutex);
499     return NULL;
500   }
501
502   unsigned char* p = (unsigned char*)tcp->receivePacket();
503   pthread_mutex_unlock(&mutex);
504   if (!p) return NULL;
505   *amountReceived = tcp->getDataLength();
506   return p;
507 }
508
509 ULLONG VDR::streamRecording(Recording* rec)
510 {
511   unsigned long totalLength = 8 + strlen(rec->fileName) + 1;
512   UCHAR buffer[totalLength];
513
514   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
515   *(unsigned long*)&buffer[4] = htonl(VDR_STREAMRECORDING);
516   strcpy((char*)&buffer[8], rec->fileName);
517
518   pthread_mutex_lock(&mutex);
519   unsigned int a = tcp->sendPacket(buffer, totalLength);
520   if (a != totalLength)
521   {
522     pthread_mutex_unlock(&mutex);
523     return 0;
524   }
525
526   unsigned char* p = (unsigned char*)tcp->receivePacket();
527   pthread_mutex_unlock(&mutex);
528   if (!p) return 0;
529
530   if (tcp->getDataLength() != 8)
531   {
532     free(p);
533     return 0;
534   }
535
536   ULLONG recordingLength = ntohll(*(ULLONG*)p);
537
538   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
539   free(p);
540
541   return recordingLength;
542 }
543
544 ULLONG VDR::rescanRecording()
545 {
546   unsigned long totalLength = 8;
547   UCHAR buffer[totalLength];
548
549   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
550   *(unsigned long*)&buffer[4] = htonl(VDR_RESCANRECORDING);
551
552   pthread_mutex_lock(&mutex);
553   unsigned int a = tcp->sendPacket(buffer, totalLength);
554   if (a != totalLength)
555   {
556     pthread_mutex_unlock(&mutex);
557     return 0;
558   }
559
560   unsigned char* p = (unsigned char*)tcp->receivePacket();
561   pthread_mutex_unlock(&mutex);
562   if (!p) return 0;
563
564   if (tcp->getDataLength() != 8)
565   {
566     free(p);
567     return 0;
568   }
569
570   ULLONG recordingLength = ntohll(*(ULLONG*)p);
571
572   Log::getInstance()->log("VDR", Log::DEBUG, "VDR said length is: %llu", recordingLength);
573   free(p);
574
575   return recordingLength;
576 }
577
578 int VDR::getChannelSchedule(ULONG number)
579 {
580   UCHAR buffer[12];
581
582   *(unsigned long*)&buffer[0] = htonl(8);
583   *(unsigned long*)&buffer[4] = htonl(VDR_GETCHANNELSCHEDULE);
584   *(unsigned long*)&buffer[8] = htonl(number);
585
586   pthread_mutex_lock(&mutex);
587   int a = tcp->sendPacket(buffer, 12);
588
589   if (a != 12)
590   {
591     pthread_mutex_unlock(&mutex);
592     return -1;
593   }
594
595   unsigned char* p = (unsigned char*)tcp->receivePacket();
596   pthread_mutex_unlock(&mutex);
597   if (!p) return -1;
598
599   int dataLength = tcp->getDataLength();
600
601   if (dataLength != 4)
602   {
603     free(p);
604     return -1;
605   }
606
607   ULONG data = ntohl(*(ULONG*)p);
608   free(p);
609
610   Log::getInstance()->log("VDR", Log::DEBUG, "Success got to end of getChannelSchedule %lu", data);
611
612   return data;
613 }
614
615 ULLONG VDR::getResumePoint(char* fileName)
616 {
617   char* resumeString = configLoad("ResumeData", fileName);
618   if (!resumeString) return 0;
619
620   ULLONG toReturn = strtoull(resumeString, NULL, 10);
621   delete[] resumeString;
622   return toReturn;
623 }
624
625 int VDR::configSave(char* section, char* key, char* value)
626 {
627   ULONG totalLength = 8 + strlen(section) + strlen(key) + strlen(value) + 3; // 8 for headers, 3 for nulls
628   UCHAR buffer[totalLength];
629
630   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
631   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGSAVE);
632
633   int position = 8;
634   strcpy((char*)&buffer[position], section);
635   position += strlen(section) + 1;
636   strcpy((char*)&buffer[position], key);
637   position += strlen(key) + 1;
638   strcpy((char*)&buffer[position], value);
639
640   pthread_mutex_lock(&mutex);
641   unsigned int a = tcp->sendPacket(buffer, totalLength);
642   if (a != totalLength)
643   {
644     pthread_mutex_unlock(&mutex);
645     return 0;
646   }
647
648   int toReturn = getSimpleReply();
649   if (toReturn == -1) toReturn = 0; // change error to bad
650   pthread_mutex_unlock(&mutex);
651   return toReturn;
652 }
653
654 char* VDR::configLoad(char* section, char* key)
655 {
656   ULONG totalLength = 8 + strlen(section) + strlen(key) + 2; // 8 for headers, 2 for nulls
657   UCHAR buffer[totalLength];
658
659   *(unsigned long*)&buffer[0] = htonl(totalLength - 4);
660   *(unsigned long*)&buffer[4] = htonl(VDR_CONFIGLOAD);
661
662   int position = 8;
663   strcpy((char*)&buffer[position], section);
664   position += strlen(section) + 1;
665   strcpy((char*)&buffer[position], key);
666
667   pthread_mutex_lock(&mutex);
668   unsigned int a = tcp->sendPacket(buffer, totalLength);
669   if (a != totalLength)
670   {
671     pthread_mutex_unlock(&mutex);
672     return NULL;
673   }
674
675   char* toReturn = getStringReply();
676   pthread_mutex_unlock(&mutex);
677   return toReturn;
678 }