/* * Copyright (C) 2005, 2006 Liu Di * * Copyright (C) 2007 Wei Lian * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "sopfork.h" #include "header.h" #include "playfork.h" #include "utils.h" #include "tabwidget.h" #include "pageplay.h" #include "mystatusbar.h" #include "record.h" #include "mainwindow.h" SopFork::SopFork (QWidget * widget, QString url, QString name, QString type, QWidget * parent, const char *name2): QObject (parent, name2), channelurl (url), channelname (name), channeltype (type), tabwidget (static_cast < TabWidget * >(parent)) { ///sop process sop = new QProcess (this); connect (sop, SIGNAL (readyReadStdout ()), this, SLOT (parseStdout ())); connect (sop, SIGNAL (processExited ()), this, SLOT (onSopExit ())); ///timer echotimer = new QTimer (this); connect (echotimer, SIGNAL (timeout ()), this, SLOT (echo ())); ///socket notifier snstatus = NULL; ///append widget to listpage listpage.append (widget); ///update message message = tr ("Connecting..."); ///fork sop forkSop (); } SopFork::~SopFork () { if (snstatus) delete snstatus; killSop (); } ////fork new process bool SopFork::forkSop () { ///select inport and outport number int i, j, sock; while (1) { i = rand () % (65536 - 3000) + 3000; ////3000 to 65535 sock = connect_to_server ("127.0.0.1", i); if (sock == -1) break; else if (sock >= 0) ::close (sock); } sprintf (inport, "%d", i); while (1) { j = rand () % (65536 - 3000) + 3000; sock = connect_to_server ("127.0.0.1", j); if (sock == -1 && j != i) break; else if (sock >= 0) ::close (sock); } sprintf (outport, "%d", j); ////fork sop process sop->clearArguments (); sop->addArgument ("sp-sc"); sop->addArgument (channelurl); sop->addArgument (inport); sop->addArgument (outport); return sop->start (); } ////kill process void SopFork::killSop () { /* if (sop->isRunning()) { // sop->tryTerminate (); sop->kill(); }*/ char sopUrl[128] = "sp-sc "; strcat (sopUrl, channelurl.ascii ()); strcat (sopUrl, " "); strcat (sopUrl, inport); strcat (sopUrl, " "); strcat (sopUrl, outport); killProcess (sopUrl, sop->processIdentifier (), sop->processIdentifier () + 10); } /////////////slots void SopFork::onSopExit () { ///restart sop if (forkSop ()) { } else fprintf (stderr, "failed to launch sp-sc!\n"); } void SopFork::parseStdout () { QString str = QString (sop->readStdout ()); if (snstatus == 0) { if (str.contains ("hook_sc") || str.contains ("downloadRate=")) { //create socket int sockfd = connect_to_server ("127.0.0.1", atoi (outport)); if (sockfd < 0) { fprintf (stderr, "failed to create socket, return err %d\n", sockfd); return; } ///bind QSocketNotifier to socket snstatus = new QSocketNotifier (sockfd, QSocketNotifier::Read, this); connect (snstatus, SIGNAL (activated (int)), SLOT (streamReady (int))); write (sockfd, "state\ns\n", sizeof ("state\ns\n")); write (sockfd, "state\ns\n", sizeof ("state\ns\n")); ///launch player, should be executed after registering snstatus for (QWidget * wd = listpage.first (); wd; wd = listpage.next ()) if (static_cast < MyVBox * >(wd)->pagetype == "play" && static_cast < PagePlay * >(wd)->buttonplayer->isOn ()) static_cast < PagePlay * >(wd)->onButtonPlayerToggled (true); ///update message message = "data"; } else if (str.contains ("detect MTU")) { ///update message message = tr ("Waiting..."); ///show message on statusbar for (QWidget * wd = listpage.first (); wd; wd = listpage.next ()) if (tabwidget->indexOf (wd) == tabwidget->currentPageIndex ()) { static_cast < MainWindow * >(qApp->mainWidget ()) ->statusbar->showMessage (message); break; } } } } void SopFork::streamReady (int fd) { char buff[64]; memset (buff, 0, sizeof (buff)); int red = 0, size, ret; size = sizeof (buff); while (1) { ret =::read (fd, buff + red, size); if (ret <= 0) ///server shutdown { if (ret < 0) perror ("status socketnotifier"); //close socket and delete socket noitifier ::close (fd); delete snstatus; snstatus = 0; ///stop timer echotimer->stop (); ///change statusbar interface ///update message message = tr ("Connecting..."); ///show message on statusbar for (QWidget * wd = listpage.first (); wd; wd = listpage.next ()) if (tabwidget->indexOf (wd) == tabwidget->currentPageIndex ()) { static_cast < MainWindow * >(qApp->mainWidget ()) ->statusbar->showMessage (message); break; } /// return; } if (strstr (buff, "\n")) break; red += ret; size -= ret; } if (buff[0] != 10) { char *savept; ::strtok_r (buff, "\n", &savept); int value[6]; value[0] = atoi (strtok_r (buff, " ", &savept)); for (int i = 1; i < 6; i++) { value[i] = atoi (strtok_r (NULL, " ", &savept)); if (i < 5) value[i] = value[i] / 1024; } static const char format[][10] = { "%d%%", "ur=%dk", "dr=%dk", "us=%dk", "ds=%dk", "peers=%d" }; for (int i = 0; i < 6; i++) { sprintf (buff, format[i], value[i]); arraymessage[i] = buff; } ///show arraymessage on statusbar for (QWidget * wd = listpage.first (); wd; wd = listpage.next ()) if (tabwidget->indexOf (wd) == tabwidget->currentPageIndex ()) { static_cast < MainWindow * >(qApp->mainWidget ()) ->statusbar->showMessage (arraymessage); break; } } else printf ("buff=10\n"); ///singleshot echotimer->start (1000, true); } void SopFork::echo () { bool found = false; ///if the current page is within the list, then update data statistics for (QWidget * wd = listpage.first (); wd; wd = listpage.next ()) if (tabwidget->indexOf (wd) == tabwidget->currentPageIndex ()) { write (snstatus->socket (), "s\n", sizeof ("s\n")); found = true; break; } if (found == false) echotimer->start (1000, true); }