SPnew.c
资源名称:p2p_vod.rar [点击查看]
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:37k
源码类别:
P2P编程
开发平台:
Visual C++
- /*
- * Openmysee
- *
- * 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 "echo.h"
- struct Argument
- {
- int type;
- int spchannelcount;
- int totalclient;
- long long totalupsize;
- FILE *f, *xml[MAX_TS];
- char *buf;
- };
- #define SPUPDATE_SLOT 1
- #define MAX_CHANNEL 1024 /* max number of Channel */
- #define SP4CP_PORT 50001
- #define TS4RM_PORT 22169
- #define RM2TS_STAT_QUERY 0x20
- #define TS2RM_STAT_RESPONSE 0x30
- int MAX_CP=512;
- int MAX_CS=32;
- int MAX_JOB_PER_SESSION=3;
- char *Home = "./";
- char *PREFIX = "/data/sp/";
- char *Database = "user.db";
- char *CONFIG = "./asp.cfg";
- char *PIDFile = "/var/run/spnew.pid";
- char *RULE = "";
- char *SERVERIP;
- char *DBFILE;
- char *MEDIABASE;
- char *AUTH_MD5;
- int AUTH_USERID;
- fd_set osocks;
- int NumNewChannel;
- struct Message TempMsg;
- char *NET_NAME[] = { "edu", "cnc", "uni", "tel" };
- long long totalDownBytes=0, totalUpBytes=0;
- long long tmpDownBytes=0, tmpUpBytes=0;
- char *urlroot;
- char *defaultspip;
- char *spip[4];
- char *tsip[4];
- #ifdef TEST
- char *WWW_ROOT;
- #endif
- #ifdef HAVE_MYSQL
- char *MYSQL_HOST;
- char *MYSQL_USER;
- char *MYSQL_PASS;
- char *MYSQL_DB;
- #endif
- char *CAS_ADDR; // Content Aggregation Server, added by lixingwu, 20070313
- int tsSock[MAX_TS];
- struct sockaddr_in tsAddr[MAX_TS];
- extern struct Channel *ChannelHash[MAX_CHANNEL];
- extern struct Channel *ChannelList;
- extern int isDelete (struct Channel *pc);
- extern int errno;
- int JobHighWater = 10000;
- int BINDALL=1;
- int AuthCS=0;
- time_t startTime;
- time_t CurrentTime;
- int PERIOD;
- int SnapShotInterval; //make a snapshot every few second
- int spuprecord[MAX_CHANNEL];
- struct ServerDesc TRACKER[MAX_TYPE];
- char *LOGXML;
- struct NamVal ConfigParameters[] = {
- {"DBdir", &Home, 's'},
- {"AuthCS", &AuthCS, 'd'},
- {"MAX_CP",&MAX_CP, 'd'},
- {"MAX_CS", &MAX_CS, 'd'},
- {"Pidfile", &PIDFile, 's'},
- {"Prefix", &PREFIX, 's'},
- {"DBfile", &Database, 's'},
- {"TrackerIP", &SERVERIP, 's'},
- {"Dir", &MEDIABASE, 's'},
- {"authid", &AUTH_USERID, 'd'},
- {"authmd5", &AUTH_MD5, 's'},
- {"periodDump", &PERIOD, 'd'}, //make a periodCheck every periodDump second
- {"UrlRoot", &urlroot, 's'},
- {"EDUSPIP", &spip[EDUTS], 's'},
- {"CNCSPIP", &spip[CNCTS], 's'},
- {"UNISPIP", &spip[UNITS], 's'},
- {"TELSPIP", &spip[TELTS], 's'},
- {"BINDALL", &BINDALL, 'd'},
- {"EDUTSIP", &tsip[EDUTS], 's'},
- {"CNCTSIP", &tsip[CNCTS], 's'},
- {"UNITSIP", &tsip[UNITS], 's'},
- {"TELTSIP", &tsip[TELTS], 's'},
- {"SnapShotInterval", &SnapShotInterval, 'd'},
- {"LogFilePath", &LOGXML, 's'},
- #ifdef TEST
- {"WWWRoot", &WWW_ROOT, 's'},
- #endif
- #ifdef HAVE_MYSQL
- {"MysqlAddress", &MYSQL_HOST, 's'},
- {"User", &MYSQL_USER, 's'},
- {"Database", &MYSQL_DB, 's'},
- {"Password", &MYSQL_PASS, 's'},
- #endif
- {"AllowCSList", &RULE, 's'},
- {"JobHighWater", &JobHighWater, 'd'},
- {"CAS_ADDR", &CAS_ADDR, 's'} // Content Aggregation Server, added by lixingwu, 20070313
- };
- extern int db_end ();
- extern int db_init (char *home, char *database);
- extern int isAllowed (int id, char *md5, char *cname, float bitrate,
- float *limitedbitrate, int *issave);
- extern char *getJobBuffer (struct JobDes *p, int *max);
- extern inline void setblockId (struct JobDes *pj, int id);
- #ifdef TEST
- int buildGTV (struct Channel *pc, int datalen, char *data, int type);
- #endif
- int send_P2P_SPUPDATE (struct Session *p, struct Channel *pc, char *md5, struct SPUpdate *s);
- int send_p2p_err (struct Session *p, unsigned short code, int quit);
- int init_sp ();
- int handle_new_connection (int sock, int type);
- int Clientclosure (int listnum, int type);
- void process_child (void);
- int init_CP (int listnum);
- int process_CP (int listnum);
- int closure_CP (int listnum);
- int init_CS (int listnum);
- int process_CS (int listnum);
- int closure_CS (int listnum);
- #ifdef HAVE_MYSQL
- MYSQL *local_mysql;
- #endif
- int process_P2P_REQUEST_real (struct Session *p, struct Channel *pc, int id);
- void apply_check (struct Channel *p, void *arg);
- void apply_idle (struct Session *p, void *arg);
- int period_process ();
- void process_TS2RM (int type);
- extern int locate_mplist_by_id (struct Channel *pc, unsigned int id, char *buf, int max);
- extern int check_newplist ();
- extern int timer_free ();
- extern int timer_process (unsigned int t);
- extern void hup_handler (int);
- #include "sessions.c"
- #define BUILD_NOCH_SPUPDATE(s) do
- {
- s.minKeySample = -1LL;
- s.maxKeySample = -1LL;
- s.minBlockID = 0xffffffff;
- s.maxBlockID = 0xffffffff;
- } while (0)
- #define BUILD_ORDER_SPUPDATE(s,pc) do
- {
- s.minKeySample = -1LL;
- s.maxKeySample = -1LL;
- s.minBlockID = 0;
- s.maxBlockID = (pc->downsize > 0 ? ((pc->downsize - 1) / DEFAULT_BLOCK) : 0)+1;
- } while (0)
- #define BUILD_CLOSE_SPUPDATE(s) do
- {
- s.minKeySample = 0;
- s.maxKeySample = 0;
- s.minBlockID = 0xffffffff;
- s.maxBlockID = 0xffffffff;
- } while (0)
- #define BUILD_MLIST_SPUPDATE(s,pc) do
- {
- s.minKeySample = -2LL;
- s.maxKeySample = pc->pcinfo->mlist->m_totalchannel;
- s.minBlockID = 0;
- s.maxBlockID = pc->pcinfo->maxID;
- } while (0)
- #define BUILD_LIVE_SPUPDATE(spupdate,pc) do
- {
- spupdate.minKeySample = -3LL;
- spupdate.maxKeySample = 1;
- spupdate.minBlockID = pc->pcinfo->s.minBlockID;
- spupdate.maxBlockID = pc->pcinfo->s.maxBlockID;
- } while (0)
- void send_all_spupdate (struct Channel *pc, struct SPUpdate *s)
- {
- struct LiveChannelInfo *pcinfo = pc->pcinfo;
- struct Edge *pedge;
- char buffer[MAX_DATA], *buf;
- if (pcinfo == NULL) return;
- pcinfo->updated = CurrentTime;
- buf = buffer + sizeof (int);
- *(unsigned char *) buf = P2P_SPUPDATE;
- buf += sizeof (char);
- memcpy (buf, pc->channel_md5, MD5_LEN);
- buf += MD5_LEN;
- if (s == NULL)
- memset (buf, 0, sizeof (struct SPUpdate));
- else
- memcpy (buf, s, sizeof (struct SPUpdate));
- buf += sizeof (struct SPUpdate);
- *(int *) buffer = buf - buffer;
- for (pedge = pc->PeerHead; pedge; pedge = pedge->cnext)
- {
- if (writeMessage (pedge->me, pc, buffer) < 0)
- {
- PDEBUG ("send SPUPDATE err.n");
- }
- }
- }
- void
- process_TS2RM (int type) //assure num of channel
- {
- int len;
- char buffer[4096];
- char *buf;
- struct sockaddr_in addr;
- int addrlen = sizeof (struct sockaddr);
- int i, msgsize, chnlnum;
- struct Channel *pChannel;
- if ((len =
- recvfrom (tsSock[type], buffer, 4096, 0,
- (struct sockaddr *) &addr, &addrlen)) < 0)
- {
- perror ("recvfrom ts");
- return;
- }
- PINFO ("got TS msg, len %d. n", len);
- buf = buffer;
- msgsize = *(int *) buf;
- buf += sizeof (int);
- if (*(unsigned char *) buf != TS2RM_STAT_RESPONSE)
- {
- perror ("bad message type from ts");
- return;
- }
- buf += sizeof (unsigned char);
- chnlnum = *(int *) buf;
- buf += sizeof (int);
- if (chnlnum > 100)
- {
- perror ("too large channel num from ts");
- return;
- }
- for (i = 0; i < chnlnum; ++i)
- {
- if ((pChannel = findChannel (buf, MD5_LEN)) == NULL)
- {
- buf += MD5_LEN;
- buf += sizeof (int);
- continue;
- }
- buf += MD5_LEN;
- pChannel->numofnp[type] = *(int *) buf;
- buf += sizeof (int);
- PINFO ("%s->%s: client %d.n",
- pChannel->pcinfo ? pChannel->channel_name : "",
- pChannel->channel_md5, pChannel->numofnp[type]);
- }
- }
- time_t lastCheck, last_snapshot;
- int
- period_process ()
- {
- int type;
- time_t tmpTime, time_interval;
- struct Argument arg;
- char buffer[MAX_DATA];
- struct tm result;
- int *querynum;
- static int snapCount = 0;
- timer_process (CurrentTime);
- check_newplist ();
- if (CurrentTime <= lastCheck + PERIOD) //PERIOD =periodDump=60
- return 0;
- memset (&arg, 0, sizeof (arg));
- tmpTime = CurrentTime - startTime;
- time_interval = CurrentTime - lastCheck;
- #ifdef HAVE_MYSQL
- query_mysql (local_mysql, "delete from channel where '1'");
- #endif
- #ifdef TEST
- for (type=0; type<MAX_TS; type++)
- {
- snprintf (buffer, MAX_DATA, "%s/%s/channel.xml", WWW_ROOT,
- NET_NAME[type]);
- if ((arg.xml[type] = fopen (buffer, "w")) == (FILE *) 0)
- {
- PDEBUG ("Error in open file %sn", buffer);
- continue;
- }
- fprintf (arg.xml[type],
- "<?xml version="1.0" encoding="gbk"?>rn<?xml:stylesheet type="text/xsl" href="simple.xsl" ?>rn<GaoV>rn");
- }
- #endif
- localtime_r (&CurrentTime, &result);
- snprintf (buffer, MAX_DATA, "./sp-%d-%d-%d.log", result.tm_year+1900, result.tm_mon+1, result.tm_mday);
- if ((arg.f = fopen (buffer, "a")) == NULL)
- {
- PDEBUG ("Couldn't open sp log file! n");
- return -1;
- }
- fprintf (arg.f, "nn********************Start %d SnapShot of SP, Time: %u/%u %u:%u:%u.n",
- snapCount++, result.tm_mon + 1, result.tm_mday, result.tm_hour,
- result.tm_min, result.tm_sec);
- fprintf(arg.f, "SP: cur Down %.4f KB. n", ((float)tmpDownBytes)/1024/time_interval);
- fprintf(arg.f, "SP: cur Up %.4f KB. n", ((float)tmpUpBytes)/1024/time_interval);
- totalDownBytes += tmpDownBytes;
- totalUpBytes += tmpUpBytes;
- fprintf(arg.f, "SP: avg Down %.4f KB. n", ((float)totalDownBytes)/1024/tmpTime);
- fprintf(arg.f, "SP: avg Up %.4f KB. n", ((float)totalUpBytes)/1024/tmpTime);
- arg.buf = buffer + sizeof (int);
- *(unsigned char *) (arg.buf) = RM2TS_STAT_QUERY;//RM2TS=0x20
- arg.buf += sizeof (unsigned char);
- querynum = (int *) (arg.buf);
- arg.buf += sizeof (int);
- arg.type = TYPE_CS;
- apply_session (TRACKER[TYPE_CS].head, TRACKER[TYPE_CS].maxid+1, apply_idle, &arg);
- /*
- arg.type = TYPE_CP;
- apply_session (TRACKER[TYPE_CP].head, TRACKER[TYPE_CP].maxid+1, apply_idle, &arg);
- */
- apply_list (ChannelList, apply_check, &arg);
- #ifdef TEST
- for (type=0; type<MAX_TS; type++)
- {
- if (arg.xml[type] == NULL)
- continue;
- fprintf (arg.xml[type], "</GaoV>rn");
- fclose (arg.xml[type]);
- }
- #endif
- fprintf (arg.f, "Channel Count : %d.Total client : %d . Total upsize :%lldB . n",
- arg.spchannelcount, arg.totalclient, arg.totalupsize);
- fprintf (arg.f,
- "n************************END SnapShot*********************n");
- fclose (arg.f);
- // added by lixingwu, 20070313
- // upload channel.xml to server, only edu
- char upload_cmd[MAX_DATA];
- sprintf(upload_cmd, "curl -F filename=@%s/%s/channel.xml -F domain=%s %s",
- WWW_ROOT, NET_NAME[EDUTS], spip[EDUTS], CAS_ADDR);
- printf("%sn", upload_cmd);
- system(upload_cmd);
- #ifdef TEST
- if (arg.spchannelcount > 0)
- {
- *querynum = arg.spchannelcount;
- *(int *) buffer = arg.buf - buffer;
- for (type=0; type<MAX_TS; type++)
- {
- if (tsSock[type] <= 0)
- continue;
- if (sendto (tsSock[type], buffer, *(int *) buffer, 0, (struct sockaddr *) &tsAddr[type], sizeof (struct sockaddr_in)) != *(int *) buffer)
- {
- PDEBUG ("sent to ts %d error. n", type);
- return 0;
- }
- }
- }
- #endif
- logto_xml (time_interval, tmpTime, arg.spchannelcount, arg.totalclient);
- lastCheck = CurrentTime;
- last_snapshot ++;
- tmpDownBytes = tmpUpBytes = 0;
- if (last_snapshot > SnapShotInterval)
- {
- system ("/usr/bin/vmstat -a >> sp.log 2>&1 &");
- last_snapshot = 0;
- }
- return 0;
- }
- int
- main (int argc, char **argv)
- {
- int i, mode = 1;
- if (argc < 2)
- {
- printf ("usage: %s mode(0 for daemon, 1 for console).n",
- argv[0]);
- return -1;
- }
- signal (SIGPIPE, SIG_IGN);
- signal (SIGINT, terminate);
- signal (SIGHUP, hup_handler);
- mode = atoi (argv[1]);
- if (mode == 0)
- daemon (1, 1);
- read_config (CONFIG, ConfigParameters,
- sizeof (ConfigParameters) / sizeof (struct NamVal));
- for (i = 0; i < 10 && IN_LOOP > 0; i++)
- {
- /*
- pid_t pid;
- if ((pid = fork ()) == 0)
- {
- */
- FD_ZERO (&osocks);
- if (init_sp () < 0) // || initLOG () < 0)
- {
- PDEBUG ("init_sp error, exit...n");
- exit (-1);
- }
- process_child ();
- /*
- } else if (pid < 0)
- {
- perror ("fork");
- exit (pid);
- } else
- {
- waitpid (pid, NULL, 0);
- }
- */
- }
- return 0;
- }
- int
- process_P2P_HELLO (struct Session *p, struct Message *m)
- {
- struct SPUpdate spupdate;
- struct Edge *pedge;
- struct Channel *pc;
- int listnum;
- PDEBUG ("CP %d.%d.%d.%d:%d join channel %.32sn",
- IPADDR (p->host), p->port, m->buffer);
- listnum = p - TRACKER[TYPE_CP].head;
- if ((pc = findChannel (m->buffer, MD5_LEN)) == NULL)
- {
- if ((pc = findOrder (m->buffer, MD5_LEN)) == NULL &&
- (pc = newOrder (m->buffer)) == NULL)
- {
- BUILD_NOCH_SPUPDATE(spupdate);
- send_P2P_SPUPDATE (p, pc, m->buffer, &spupdate);
- PDEBUG ("Cannot find channel %.32sn",
- m->buffer);
- //Clientclosure (listnum, TYPE_CP);
- } else
- {
- BUILD_ORDER_SPUPDATE(spupdate,pc);
- send_P2P_SPUPDATE (p, pc, m->buffer, &spupdate);
- PDEBUG ("channel %.32s spupdate %d~%d. n",
- m->buffer, spupdate.minBlockID,
- spupdate.maxBlockID);
- }
- } else
- {
- for (pedge = p->header; pedge && pedge->head == pc;
- pedge = pedge->enext);
- if (!pedge)
- {
- pedge = newEdge (pc, p);
- pc->numclient++;
- }
- if (pc->pcinfo)
- {
- if (pc->pcinfo->status > 0)
- {
- // this channel has been closed
- BUILD_CLOSE_SPUPDATE(spupdate);
- send_P2P_SPUPDATE (p, pc, m->buffer, &spupdate);
- PDEBUG ( "channel %.32s has been closed. n",
- m->buffer);
- //Clientclosure (listnum, TYPE_CP);
- } else if (pc->pcinfo->mlist != NULL)
- {
- BUILD_MLIST_SPUPDATE (spupdate, pc);
- send_P2P_SPUPDATE (p, pc, m->buffer, &spupdate);
- sendMedia (p, pc);
- PDEBUG ("Channel %.32s is a playlist.n", m->buffer);
- } else
- {
- BUILD_LIVE_SPUPDATE(spupdate,pc);
- send_P2P_SPUPDATE (p, pc, m->buffer, &spupdate);
- sendMedia (p, pc);
- }
- } else
- {
- BUILD_ORDER_SPUPDATE(spupdate,pc);
- send_P2P_SPUPDATE (p, pc, m->buffer, &spupdate);
- PDEBUG ("channel %.32s spupdate %d~%d. n",
- m->buffer, spupdate.minBlockID,
- spupdate.maxBlockID);
- }
- }
- return 0;
- }
- int
- process_P2P_PUSHLIST (struct Session *p, struct Message *m)
- {
- struct Edge *pedge;
- struct Channel *pc;
- char *buf;
- int i,size, type;
- if ((pc = findChannel (m->buffer, MD5_LEN)) == NULL)
- pc = newOrder (m->buffer);
- else if (pc->pcinfo != NULL)
- {
- for (pedge = p->header; pedge && pedge->head != pc;
- pedge = pedge->enext);
- if (pedge == NULL)
- {
- pedge = newEdge (pc, p);
- pc->numclient++;
- }
- }
- if (pc == NULL)
- return -1;
- if (p->numjob >= MAX_JOB_PER_SESSION)
- return -2;
- buf = m->buffer + MD5_LEN;
- type = *(unsigned char *) buf;
- buf += sizeof (char);
- size = *(unsigned char *) buf;
- buf += sizeof (char);
- if (type)
- {
- deleteChannel (p, pc);
- for (i=0; i<size; i++)
- if (process_P2P_REQUEST_real (p, pc, ((unsigned int *)buf)[i]) < 0)
- return -1;
- } else
- {
- for (i=0; i<size; i++)
- if (process_P2P_REQUEST_real (p, pc, ((unsigned int *)buf)[i]) < 0)
- return -1;
- buf += size * sizeof (int);
- size = *(unsigned char *) buf;
- buf += sizeof (char);
- deleteJob (p, pc, (unsigned int *) buf, size);
- }
- return 0;
- }
- int
- process_P2P_REQUEST_real (struct Session *p, struct Channel *pc, int id)
- {
- struct JobDes *pj = newJob ();
- char *buf, *buffer;
- int listnum, size=0, max;
- struct SPUpdate spupdate;
- if (pj == NULL) return -1;
- buffer = getJobBuffer (pj, &max);
- listnum = p - TRACKER[TYPE_CP].head;
- buf = buffer + sizeof (int);
- *(unsigned char *) buf = P2P_RESPONSE;
- buf += sizeof (char);
- memcpy (buf, pc->channel_md5, MD5_LEN);
- buf += MD5_LEN;
- if (pc->pcinfo == NULL)
- {
- *(int *) buf = id;
- buf += sizeof (int);
- if ((size =
- locate_order_by_id (pc, id, buf + sizeof (int),
- max)) < 0 && size != -2)
- {
- // BLOCK NOT FOUND
- spupdate.minKeySample = -1LL;
- spupdate.maxKeySample = -1LL;
- spupdate.minBlockID = 0xffffffff;
- spupdate.maxBlockID = 0xffffffff;
- send_P2P_SPUPDATE (p, pc, pc->channel_md5, &spupdate);
- size = 0;
- *(int *) buf = 0;
- buf += sizeof (int);
- } else if (size == -2)
- {
- PDEBUG ("Leave blocks %d to next round.n", id);
- return -1;
- } else
- {
- // block found
- *(int *) buf = size;
- buf += sizeof (int) + size;
- p->last_transferblock = CurrentTime;
- }
- // Clientclosure (listnum, TYPE_CP);
- } else if (id >= 0 && pc->pcinfo->mlist != NULL
- && (size = locate_mplist_by_id (pc, id, buf, max - 32)) > 0)
- {
- p->last_transferblock = CurrentTime;
- buf += 2 * sizeof (int) + size;
- } else if (id >= 0 && pc->pcinfo->mlist == NULL
- && (size = locate_by_id (pc, id, buf, max - 32)) > 0)
- {
- p->last_transferblock = CurrentTime;
- buf += 2 * sizeof (int) + size;
- } else if (size == -2)
- {
- assert (0);
- PDEBUG ("Leave blocks %d to next round.n", id);
- return -1;
- } else
- {
- *(int *) buf = id;
- buf += sizeof (int);
- size = 0;
- *(int *) buf = 0;
- buf += sizeof (int);
- PDEBUG ("Cannot find block id %d required by client %d.%d.%d.%d.n",
- id, IPADDR (p->host));
- }
- *(int *) buffer = buf - buffer;
- setblockId (pj, id);
- writeDATAMessage (p, pc, pj);
- // PDEBUG ("Write block %d to %d.%d.%d.%dn", id,
- // IPADDR (p->host));
- return 0;
- }
- int
- init_CP (int listnum)
- {
- return 0;
- }
- int
- process_CP (int listnum)
- {
- int ret;
- struct Session *p = &(TRACKER[TYPE_CP].head[listnum]);
- struct Message *m = (struct Message *) (p->buf + p->start);
- tmpDownBytes += m->len;
- switch (m->type)
- {
- case P2P_HELLO:
- ret= process_P2P_HELLO (p, m);
- break;
- case P2P_PUSHLIST:
- ret = process_P2P_PUSHLIST (p, m);
- break;
- case P2P_MSG:
- break;
- default:
- ret = -1;
- break;
- }
- switch (ret)
- {
- case -1:
- PDEBUG ("Message processing error from client %d.%d.%d.%dn",
- IPADDR (p->host));
- Clientclosure (listnum, TYPE_CP);
- return -1;
- case -2:
- return -2;
- default:
- return 0;
- }
- }
- int
- closure_CP (int listnum)
- {
- struct Session *p = &(TRACKER[TYPE_CP].head[listnum]);
- // struct Channel *pc = p->pc;
- struct Edge *pedge, *nextedge;
- PDEBUG ("CP disconnected from %d.%d.%d.%d:%dn",
- IPADDR (p->host), p->port);
- for (pedge = p->header; pedge; pedge = nextedge)
- {
- nextedge = pedge->enext;
- if (pedge->head)
- pedge->head->numclient--;
- delEdge (pedge);
- }
- FD_CLR (p->socket, &osocks);
- close (p->socket);
- FREE (p->buf);
- deleteAll (p);
- memset (p, 0, sizeof (struct Session));
- return 0;
- }
- int
- init_CS (int listnum)
- {
- return 0;
- }
- int
- process_CS2SP_REGISTER (int listnum, char *msg)
- {
- int i, errmsg;
- char cname[MAX_LINE], cmd5[MD5_LEN + 1], buffer[MAX_DATA];
- //char escape_buf[MAX_LINE];
- char md5[MD5_LEN + 1];
- struct Session *p = &(TRACKER[TYPE_CS].head[listnum]), *source;
- struct Channel *pc;
- float bitrate, limitedbitrate=10000.0;
- int id, startblock, size, maxblocksize, datalen, issave=0;
- size = *(unsigned char *) msg;
- msg += sizeof (char);
- if (size > sizeof (cname) || size <= 0) //wrong Message
- {
- Clientclosure (listnum, TYPE_CS);
- return -1;
- } else
- memcpy (cname, msg, size);
- cname[size] = 0;
- msg += size;
- // memcpy (cmd5, msg, MD5_LEN);
- // msg += MD5_LEN;
- id = *(int *) msg;
- msg += sizeof (int);
- sprintf (buffer, "%d@%s_%s", id, defaultspip, cname);
- md5_calc ((unsigned char *) md5, (unsigned char *) buffer,
- strlen (buffer));
- for (i = 0; i < MD5_LEN; i += 2)
- sprintf (cmd5 + i, "%02x", (unsigned char) md5[i / 2]);
- cmd5[MD5_LEN] = 0;
- memcpy (md5, msg, MD5_LEN);
- msg += MD5_LEN;
- maxblocksize = *(int *) msg;
- msg += sizeof (int);
- bitrate = *(float *) msg;
- msg += sizeof (float);
- datalen = *(unsigned short *) msg;
- if (datalen > MAX_LINE)
- {
- Clientclosure (listnum, TYPE_CS);
- return -1;
- }
- msg += sizeof (short);
- if (AuthCS && (errmsg =
- isAllowed (id, md5, cname, bitrate, &limitedbitrate, &issave)) < 0)
- {
- PDEBUG ("User %d is not allowed to newchannel %s.n",
- id, cname);
- send_p2p_err (p, -errmsg, 1);
- Clientclosure (listnum, TYPE_CS);
- return -1;
- }
- startblock = 0;
- if ((pc = findChannel (cmd5, MD5_LEN)) != NULL)
- {
- if (pc->pcinfo == NULL || pc->pcinfo->mlist != NULL)
- {
- PDEBUG ("The channel %s is a playlist.n", cname);
- send_p2p_err (p, ERR_INTERNAL, 1);
- Clientclosure (listnum, TYPE_CS);
- return -1;
- }
- if ((source = pc->pcinfo->dataSource) != NULL)
- {
- Clientclosure (source - TRACKER[TYPE_CS].head,
- TYPE_CS);
- }
- }
- if ((pc = newLiveChannel (cname, p, cmd5, bitrate,
- maxblocksize)) != (struct Channel *) 0)
- {
- p->pc = pc;
- pc->pcinfo->userid = id;
- pc->pcinfo->limitedBitRate = limitedbitrate;
- pc->pcinfo->isSave = issave;
- pc->pcinfo->dataSource = &(TRACKER[TYPE_CS].head[listnum]);
- pc->pcinfo->startid = pc->pcinfo->maxID = (CurrentTime - FIX_MAGIC) * 16;
- } else
- {
- PDEBUG ("newLiveChannel failed.n");
- send_p2p_err (p, ERR_INTERNAL, 1);
- Clientclosure (listnum, TYPE_CS);
- return -1;
- }
- *(int *) buffer = 9;
- *(char *) (buffer + sizeof (int)) = SP2CS_WELCOME;
- *(int *) (buffer + sizeof (int) + sizeof (char)) = startblock;
- if (writeMessage (p, pc, buffer) < 0)
- {
- send_p2p_err (p, ERR_INTERNAL, 1);
- Clientclosure (listnum, TYPE_CS);
- return -1;
- }
- pc->pcinfo->cur_channel = pc->pcinfo->max_channel = 1;
- pc->pcinfo->media = calloc (1, sizeof (struct MediaData));
- pc->pcinfo->media[0].start = 0;
- pc->pcinfo->media[0].len = -1;
- pc->pcinfo->media[0].dlen = datalen;
- pc->pcinfo->media[0].data = calloc (1, datalen);
- memcpy (pc->pcinfo->media[0].data, msg, datalen);
- #ifdef TEST
- /*
- for (type = 0; type < MAX_TS; ++type)
- buildGTV (pc, datalen, msg, type);
- */
- for (i=0; i<MAX_TS; i++) {
- if (buildGTV (pc, datalen, msg, i) < 0)
- continue;
- }
- #endif
- #ifdef HAVE_MYSQL
- // query_mysql (local_mysql, "delete from channel where ChannelMD5 = "%s"", cmd5);
- // mysql_escape_string (escape_buf, msg, datalen);
- // query_mysql (local_mysql, "insert into channel (ChannelName, ChannelBitrate, ChannelAttachData, ChannelMD5, ChannelOwnerID) values ("%s","%f", "%s", "%s", "%d")", cname, bitrate, escape_buf, cmd5, id);
- #endif
- return 0;
- }
- int
- process_CS2SP_UPDATE (int listnum, float rate) //only update bitrate
- {
- struct Session *p = &(TRACKER[TYPE_CS].head[listnum]);
- struct Channel *pc = p->pc;
- struct LiveChannelInfo *pcinfo = pc->pcinfo;
- pcinfo->bitrate = rate;
- if (rate > pcinfo->limitedBitRate)
- {
- send_p2p_err (p, ERR_EXCEED_BITRATE, 1);
- Clientclosure (listnum, TYPE_CS);
- return -1;
- }
- #ifdef HAVE_MYSQL
- // query_mysql (local_mysql, "update channel set ChannelBitrate = "%f" where ChannelMD5 = "%s"", rate, pc->channel_md5);
- #endif
- return 0;
- }
- int
- process_CS2SP_BLOCK (int listnum, char *msg)
- {
- char *buf, buffer[MAX_DATA];
- struct Edge *pedge;
- int size; // max=TRACKER[TYPE_CP].maxid+1;
- struct Session *p = &(TRACKER[TYPE_CS].head[listnum]);
- // struct Session *q=TRACKER[TYPE_CP].head;
- struct Channel *pc = p->pc;
- struct LiveChannelInfo *pcinfo;
- if (p->pc == NULL || (pcinfo = p->pc->pcinfo) == NULL || pcinfo->mlist != NULL)
- {
- PDEBUG ("Unmatched channeln");
- Clientclosure (listnum, TYPE_CS);
- return -1;
- }
- pcinfo = p->pc->pcinfo;
- if ((size = saveBlock (pc, msg, p)) > 0)
- {
- // directly send this block to connected CPs
- buf = buffer + sizeof (int);
- *(unsigned char *) buf = P2P_RESPONSE;
- buf += sizeof (char);
- memcpy (buf, pc->channel_md5, MD5_LEN);
- buf += MD5_LEN;
- p->last_transferblock = CurrentTime;
- memcpy (buf, msg, size + 2 * sizeof (int));
- buf += size + 2 * sizeof (int);
- *(int *) buffer = buf - buffer;
- for (pedge = pc->PeerHead; pedge; pedge = pedge->cnext)
- {
- if (pedge->me->numjob >= MAX_JOB_PER_SESSION)
- continue;
- pedge->me->last_transferblock = CurrentTime;
- // PDEBUG ("write %u ",
- // ((unsigned int *) msg)[0]);
- if (-1 == writeMessage (pedge->me, pc, buffer))
- PDEBUG ("buffer is fulln");
- // else
- // PDEBUG ("OKn");
- }
- if (pcinfo->updated <= CurrentTime + SPUPDATE_SLOT) //pcinfo is livechannel
- send_all_spupdate (pc, &(pcinfo->s));
- } else
- {
- PDEBUG ("save Block Failed ! size %d, %dn", size,
- listnum);
- Clientclosure (listnum, TYPE_CS);
- }
- return 0;
- }
- int
- process_CS (int listnum)
- {
- struct Session *p = &(TRACKER[TYPE_CS].head[listnum]);
- struct Message *m = (struct Message *) (p->buf + p->start);
- tmpDownBytes += m->len;
- switch (m->type)
- {
- case CS2SP_REGISTER:
- process_CS2SP_REGISTER (listnum, m->buffer);
- break;
- case CS2SP_UPDATE:
- process_CS2SP_UPDATE (listnum,
- *(float *) (m->buffer));
- break;
- case CS2SP_BLOCK:
- process_CS2SP_BLOCK (listnum, m->buffer);
- break;
- default:
- Clientclosure (listnum, TYPE_CS);
- return -1;
- }
- return 0;
- }
- int
- closure_CS (int listnum)
- {
- struct Session *p = &(TRACKER[TYPE_CS].head[listnum]);
- struct Channel *pc = p->pc;
- PDEBUG ("CS disconnected from %d.%d.%d.%d:%dn",
- IPADDR (p->host), p->port);
- if (pc)
- {
- if (pc->pcinfo)
- {
- pc->pcinfo->dataSource = NULL;
- pc->pcinfo->status = 1;
- }
- freeLiveChannel (pc, NULL);
- }
- FD_CLR (TRACKER[TYPE_CS].head[listnum].socket, &osocks);
- close (TRACKER[TYPE_CS].head[listnum].socket);
- FREE (p->buf);
- deleteAll (p);
- memset (&(TRACKER[TYPE_CS].head[listnum]), 0,
- sizeof (struct Session));
- return 0;
- }
- int
- init_sp ()
- {
- FILE *pidf;
- struct rlimit rl;
- char *index;
- int type;
- char buffer[MAX_DATA];
- rl.rlim_cur = rl.rlim_max = 1000000;
- if (setrlimit (RLIMIT_NOFILE, &rl) != 0)
- {
- perror ("setrlimit");
- }
- for (type=0; type<MAX_TS; type++)
- {
- if (spip[type] != NULL && strlen (spip[type]) >= MIN_IPADDR_LEN)
- {
- defaultspip = spip[type];
- break;
- }
- }
- if (defaultspip == NULL)
- defaultspip = "127.0.0.1";
- OPENLOG;
- #ifdef DEBUG
- system ("ulimit -a");
- if (getrlimit (RLIMIT_CORE, &rl) != 0)
- {
- perror ("getrlimit");
- }
- PDEBUG ("Get core limit %d:%dn", (int)rl.rlim_cur, (int)rl.rlim_max);
- rl.rlim_cur = rl.rlim_max = (rlim_t )10240000;
- if (setrlimit (RLIMIT_CORE, &rl) != 0)
- {
- perror ("setrlimit");
- }
- if (getrlimit (RLIMIT_CORE, &rl) != 0)
- {
- perror ("getrlimit");
- }
- PDEBUG ("Set core limit to %d:%dn", (int)rl.rlim_cur, (int)rl.rlim_max);
- system ("ulimit -a");
- #endif
- #ifdef HAVE_MYSQL
- if ((local_mysql =
- init_mysql (MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB,
- "/var/run/mysqld/mysqld.sock")) == 0)
- {
- PDEBUG ("Error in init_mysql.n");
- exit (1);
- }
- #endif
- TRACKER[TYPE_CP].type = TYPE_CP; //allocate CP ServerDesc TYPE_CP = 0
- TRACKER[TYPE_CP].port = SP4CP_PORT; //SP4CP_PORT = 50001
- TRACKER[TYPE_CP].cur = 0; //current client connection
- TRACKER[TYPE_CP].max = MAX_CP; //MAX_CP = 2048
- TRACKER[TYPE_CP].init = init_CP; //the function pointer of init_CP,return a debug message
- TRACKER[TYPE_CP].process = process_CP; //the function pointer of process_CP, switch TYPE
- TRACKER[TYPE_CP].closure = closure_CP; //the funciont pointer of closure_CP,return debug msg and freejob
- TRACKER[TYPE_CP].head = calloc (sizeof (struct Session), TRACKER[TYPE_CP].max); //allocate session memory
- switch (BINDALL)
- {
- case 0:
- if ((TRACKER[TYPE_CP].sock = init_server (spip[0], SP4CP_PORT)) < 0) //PORT = 50001
- return -1;
- break;
- default:
- if ((TRACKER[TYPE_CP].sock = init_server (NULL, SP4CP_PORT)) < 0) //PORT = 50001
- return -1;
- break;
- }
- FD_SET (TRACKER[TYPE_CP].sock, &osocks);
- TRACKER[TYPE_CS].type = TYPE_CS; //allocate CP ServerDese,TYPE_CS = 1
- TRACKER[TYPE_CS].port = SP4CS_PORT;
- TRACKER[TYPE_CS].cur = 0;
- TRACKER[TYPE_CS].max = MAX_CS; //MAX_CS = 512
- TRACKER[TYPE_CS].init = init_CS; //return a debug message
- TRACKER[TYPE_CS].process = process_CS;
- TRACKER[TYPE_CS].closure = closure_CS;
- TRACKER[TYPE_CS].head =
- calloc (sizeof (struct Session), TRACKER[TYPE_CS].max);
- switch (BINDALL)
- {
- case 0:
- if ((TRACKER[TYPE_CS].sock = init_server (spip[0], SP4CS_PORT)) < 0) //port =
- return -1;
- break;
- default:
- if ((TRACKER[TYPE_CS].sock = init_server (NULL, SP4CS_PORT)) < 0) //port =
- return -1;
- break;
- }
- FD_SET (TRACKER[TYPE_CS].sock, &osocks);
- if (db_init (Home, Database) < 0)
- return -1;
- memset (tsAddr, 0, sizeof (struct sockaddr_in) * MAX_TS); //sockaddr_in type
- for (type = 0; type < MAX_TS; ++type)
- {
- #ifdef TEST
- sprintf (buffer, "rm -f %s/%s/*.gtv", WWW_ROOT,
- NET_NAME[type]);
- system (buffer);
- sprintf (buffer, "rm -f %s/%s/*.mediadata", WWW_ROOT,
- NET_NAME[type]);
- system (buffer);
- sprintf (buffer, "rm -f %s/%s/channel.xml", WWW_ROOT,
- NET_NAME[type]);
- system (buffer);
- #endif
- sprintf (buffer, "rm -fr %s/%s/*", PREFIX, LIVE_PREFIX);
- system (buffer);
- if (tsip[type] == NULL) continue;
- tsAddr[type].sin_family = AF_INET;
- tsAddr[type].sin_port = htons (TS4RM_PORT);
- index = strchr (tsip[type], ':');
- if (index == NULL)
- inet_aton (tsip[type], &tsAddr[type].sin_addr);
- else
- {
- *index = 0;
- inet_aton (tsip[type], &tsAddr[type].sin_addr);
- *index = ':';
- }
- tsSock[type] = socket (PF_INET, SOCK_DGRAM, 0); //upd connection
- if (tsSock[type] < 0)
- return -1;
- }
- mkdir (PREFIX, 0777);
- sprintf (buffer, "%s/%s", PREFIX, LIVE_PREFIX);
- mkdir (buffer, 0777);
- sprintf (buffer, "%s/%s", PREFIX, ORDER_PREFIX);
- mkdir (buffer, 0777);
- sprintf (buffer, "%s/%s", PREFIX, PLIST_PREFIX);
- mkdir (buffer, 0777);
- sprintf (buffer, "%s/%s", PREFIX, PROG_PREFIX);
- mkdir (buffer, 0777);
- if ((pidf = fopen (PIDFile, "w")) == NULL)
- {
- PDEBUG ("Cannot open pidfile.n");
- return -1;
- }
- fprintf (pidf, "%dn", getpid ());
- fclose (pidf);
- return 0;
- }
- #ifdef TEST
- /*
- int
- buildMediaData (struct Channel *pc, int datalen, char *data, int type)
- {
- int i;
- char olddata[MAX_DATA];
- char buffer[MAX_DATA];
- struct stat stbuf;
- FILE *f;
- assert (pc->pcinfo);
- snprintf (buffer, MAX_LINE, "%s/%s/%s.mediadata", WWW_ROOT, NET_NAME[type], pc->channel_name);
- if (stat (buffer, &stbuf) == 0)
- {
- if (stbuf.st_size != datalen)
- {
- PDEBUG ("old media data size %d not match new %dn", (int)(stbuf.st_size), datalen);
- return -1;
- }
- if ((f = fopen (buffer, "r")) == NULL)
- {
- PDEBUG ("cannot open mediadata file %sn", buffer);
- perror ("fopen");
- return -1;
- }
- if (fread (olddata, datalen, 1, f) == 1)
- {
- for (i=0; i<datalen; i++)
- {
- if (data[i] != olddata[i])
- {
- PDEBUG ("media data not match %s, %dn", buffer, i);
- fclose (f);
- return -1;
- }
- }
- } else
- {
- PDEBUG ("Error in read old mediadata %s.n", buffer);
- fclose (f);
- return -1;
- }
- fclose (f);
- return 0;
- } else if ((f = fopen (buffer, "w")) == NULL)
- {
- PDEBUG ("cannot open gtv file %sn", buffer);
- perror ("fopen");
- return -1;
- }
- fwrite (data, datalen, 1, f);
- fclose (f);
- return 0;
- }
- */
- int
- buildGTV (struct Channel *pc, int datalen, char *data, int type)
- {
- char buffer[MAX_DATA];
- FILE *f;
- assert (pc->pcinfo);
- snprintf (buffer, MAX_LINE, "%s/%s/%s.gtv", WWW_ROOT, NET_NAME[type], pc->channel_name);
- // snprintf (buffer, MAX_LINE, "%s/%s.gtv", pc->fname, pc->channel_name);
- if ((f = fopen (buffer, "w")) == NULL)
- {
- PDEBUG ("cannot open gtv file %sn", buffer);
- perror ("fopen");
- return -1;
- }
- if (pc->pcinfo)
- {
- if (pc->pcinfo->mlist != NULL)
- sprintf (buffer,
- "CSUserID=%drnBlockSize=%drnBitRate=%frnChannelName=%srnPlaylist=truernResourceHash=%srnTrackServer=%srnSuperPeer=%s:50001rnDataLength=%drnData=",
- pc->pcinfo->userid, pc->maxblocksize, pc->pcinfo->bitrate,
- pc->channel_name, pc->channel_md5, tsip[type], spip[type],
- datalen);
- else
- sprintf (buffer,
- "CSUserID=%drnBlockSize=%drnBitRate=%frnChannelName=%srnResourceHash=%srnTrackServer=%srnSuperPeer=%s:50001rnDataLength=%drnData=",
- pc->pcinfo->userid, pc->maxblocksize, pc->pcinfo->bitrate,
- pc->channel_name, pc->channel_md5, tsip[type], spip[type],
- datalen);
- } else
- sprintf (buffer,
- "GTVHome=%s/rnBlockSize=%drnResourceHash=%srnTrackServer=%srnSuperPeer=%s:50001rnDataLength=%drnData=",
- urlroot, pc->maxblocksize, pc->channel_md5,
- tsip[type], spip[type], datalen);
- fwrite (buffer, strlen (buffer), 1, f);
- fwrite (data, datalen, 1, f);
- fclose (f);
- /* snprintf (buffer, MAX_LINE, "%s/%s/%s.mediadata", WWW_ROOT, NET_NAME[type], pc->channel_name);
- if (stat (buffer, &stbuf) == 0)
- {
- if (stbuf.st_size != datalen)
- {
- PDEBUG ("old media data size %d not match new %dn", (int)(stbuf.st_size), datalen);
- return -1;
- }
- if ((f = fopen (buffer, "r")) == NULL)
- {
- PDEBUG ("cannot open mediadata file %sn", buffer);
- perror ("fopen");
- return -1;
- }
- if (fread (olddata, datalen, 1, f) == 1)
- {
- for (i=0; i<datalen; i++)
- {
- if (data[i] != olddata[i])
- {
- PDEBUG ("media data not match %s, %dn", buffer, i);
- fclose (f);
- return -1;
- }
- }
- } else
- {
- PDEBUG ("Error in read old mediadata %s.n", buffer);
- fclose (f);
- return -1;
- }
- fclose (f);
- return 0;
- } else if ((f = fopen (buffer, "w")) == NULL)
- {
- PDEBUG ("cannot open gtv file %sn", buffer);
- perror ("fopen");
- return -1;
- }
- fwrite (data, datalen, 1, f);
- fclose (f);
- */
- // added by lixingwu, 20070313
- // upload gtv files to server
- char upload_cmd[MAX_DATA];
- sprintf(upload_cmd, "curl -F filename=@%s/%s/%s.gtv -F domain=%s %s",
- WWW_ROOT, NET_NAME[type], pc->channel_name, spip[type], CAS_ADDR);
- printf("%sn", upload_cmd);
- system(upload_cmd);
- return 0;
- }
- #endif
- int
- send_P2P_SPUPDATE (struct Session *p, struct Channel *pc, char *md5, struct SPUpdate *s)
- {
- char buffer1[MAX_DATA];
- char *buf;
- buf = buffer1 + sizeof (int);
- *(unsigned char *) buf = P2P_SPUPDATE; //P2P_SPUPDATE=1 in ProTocol file
- buf += sizeof (char);
- memcpy (buf, md5, MD5_LEN);
- buf += MD5_LEN;
- memcpy (buf, s, sizeof (struct SPUpdate));
- buf += sizeof (struct SPUpdate);
- *(int *) buffer1 = buf - buffer1;
- if (writeMessage (p, pc, buffer1) < 0)
- return -1;
- return 0;
- }
- int
- send_p2p_err (struct Session *p, unsigned short code, int quit)
- {
- char buffer1[MAX_DATA];
- char *buf;
- buf = buffer1 + sizeof (int);
- *(unsigned char *) buf = P2P_MSG;
- buf += sizeof (char);
- (*(unsigned short *) buf) = code;
- buf += sizeof (short);
- *(int *) buf = quit;
- buf += sizeof (int);
- *(int *) buffer1 = buf - buffer1;
- PDEBUG ("Send error msg type %hd to %pn", code, p);
- if (writeMessage (p, NULL, buffer1) < 0)
- return -1;
- return 0;
- }
- void apply_idle (struct Session *p, void *arg)
- {
- struct Argument *parg = (struct Argument *)arg;
- if (CurrentTime - p->last_transferblock >= MAX_TRANSFER_IDLE)
- {
- fprintf (parg->f, "%s Session timeout! %ld n", parg->type == TYPE_CS? "CS":"CP", CurrentTime - p->last_transferblock);
- Clientclosure (p - TRACKER[parg->type].head, parg->type);
- }
- }
- void apply_check (struct Channel *p, void *arg)
- {
- struct Argument *parg = (struct Argument *)arg;
- int type;
- struct LiveChannelInfo *pc = p->pcinfo;
- if (pc && pc->status <= 0)
- {
- #ifdef HAVE_MYSQL
- query_mysql (local_mysql,
- "insert into channel(ChannelName, ChannelBitrate, ChannelMD5, ChannelElapsed, ChannelRange) values ('%s','%f','%d','%d')",
- pc->channel_name, pc->bitrate,
- p->channel_md5,
- time (NULL) - p->ctime,
- pc->s.maxKeySample -
- pc->s.minKeySample);
- #endif
- #ifdef TEST
- for (type=0; type<MAX_TS; type++)
- {
- if (parg->xml[type] == NULL)
- continue;
- fprintf (parg->xml[type], "<Channel Name="%s" Desc="%s" File="%s.gtv" NumClient="%d" BitRate="%d" Start="%ld" End="-1" Elapsed="%ld"/>rn",
- p->channel_name, "gtv", //pc->userid,
- p->channel_name, p->numofnp[type],
- (int) (pc->bitrate * 8),
- (long) p->ctime, (long) CurrentTime);
- }
- #endif
- PINFO ("query %s->%s n",
- p->channel_name, p->channel_md5);
- memcpy (parg->buf, p->channel_md5, MD5_LEN);
- parg->buf += MD5_LEN;
- fprintf (parg->f, "Channel %s have %d client. upsize %lldB, avg speed %f; downsize %lldB, avg speed %f, reported %f, real/reported is %f%%.n",
- p->channel_md5, p->numclient,
- p->upsize, ((float)(p->upsize)) / (CurrentTime - lastCheck), p->downsize, ((float)(p->downsize)) / (CurrentTime - lastCheck), p->pcinfo !=NULL ? p->pcinfo->bitrate:0, p->pcinfo != NULL && p->pcinfo->bitrate != 0 ? (((float)(p->downsize)) / (CurrentTime - lastCheck)*100/p->pcinfo->bitrate): 0);
- fprintf (parg->f, "Live SPUpdate : SampleMin %lld SampleMax %lld BlockMin %d BlockMax %d n",
- pc->s.minKeySample,
- pc->s.maxKeySample,
- pc->s.minBlockID,
- pc->s.maxBlockID);
- parg->spchannelcount ++;
- parg->totalclient += p->numclient;
- parg->totalupsize += p->upsize;
- } else if (pc && pc->isSave == 0)
- freeLiveChannel (p, NULL);
- }