program.c
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:9k
源码类别:

P2P编程

开发平台:

Visual C++

  1. /*
  2.  *  Openmysee
  3.  *
  4.  *  This program is free software; you can redistribute it and/or modify
  5.  *  it under the terms of the GNU General Public License as published by
  6.  *  the Free Software Foundation; either version 2 of the License, or
  7.  *  (at your option) any later version.
  8.  *
  9.  *  This program is distributed in the hope that it will be useful,
  10.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *  GNU General Public License for more details.
  13.  *
  14.  *  You should have received a copy of the GNU General Public License
  15.  *  along with this program; if not, write to the Free Software
  16.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17.  *
  18.  */
  19.  
  20. #include "echo.h"
  21. extern time_t CurrentTime;
  22. extern char *PREFIX;
  23. static struct Channel *ProgramHash[MAX_CHANNEL];
  24. static struct Channel *ProgramList;
  25. static int NumNewProg;
  26. static struct Channel *findProgram (char *name, int len)
  27. {
  28. return getChannel (ProgramHash, name, len);
  29. }
  30. #define skipSeparator(ptr,end) do
  31. {
  32. while ((*ptr == '=' || isspace (*ptr)) && ptr < end) ptr ++;
  33. } while (0)
  34. #define skipSpace(ptr,end) do
  35. {
  36. while (isspace (*ptr) && ptr < end) ptr ++;
  37. } while (0)
  38. #define skipNonalnum(ptr,end) do
  39. {
  40. while ((!isalnum (*ptr)) && ptr < end) ptr ++;
  41. } while (0)
  42. #define lineup(ptr,end) do
  43. {
  44. while (*ptr != 'r' && *ptr != 'n' && ptr < end) ptr ++;
  45. } while (0)
  46. #define copyStr(src,dst,max,end) do
  47. {
  48. while ((!isspace (*ptr)) && max >= 0 && ptr < end)
  49. {
  50. *dst++ = *src++;
  51. max --;
  52. }
  53. *dst = 0;
  54. } while (0)
  55. static int read_prog_config (char *name, char *cname, int maxlen, float *bitrate, int *bsize, int *datalen, char **data)
  56. {
  57. int len, size;
  58. FILE *in;
  59. char *buffer=NULL, *ptr, *end;
  60. char *p, *dst;
  61. struct stat stbuf;
  62. if (stat (name, &stbuf) != 0 || !(S_ISREG (stbuf.st_mode)))
  63. {
  64. PDEBUG ("Config file %s does not exist.n", name);
  65. return -1;
  66. }
  67. if ((in=fopen (name, "r")) == NULL)
  68. {
  69. PDEBUG ("Cannot open file %sn", name);
  70. return -1;
  71. }
  72. size = stbuf.st_size;
  73. buffer = calloc (1, size+1);
  74. if (fread (buffer, size, 1, in) != 1)
  75. {
  76. PDEBUG ("Cannot read all the file %s.n", name);
  77. fclose (in);
  78. free (buffer);
  79. return -1;
  80. }
  81. end = buffer + size + 1;
  82. for (ptr=buffer; ptr<end;)
  83. {
  84. skipSpace (ptr, end);
  85. if (strncasecmp (ptr, "ChannelName", strlen ("ChannelName")) == 0)
  86. {
  87. ptr += strlen ("ChannelName");
  88. if (isalnum (*ptr))
  89. {
  90. lineup (ptr,end);
  91. continue;
  92. }
  93. skipSeparator(ptr,end);
  94. if (ptr >= end) break;
  95. copyStr (ptr, cname, maxlen,end);
  96. lineup (ptr,end);
  97. }
  98. else if (strncasecmp (ptr, "BitRate", strlen ("BitRate")) == 0)
  99. {
  100. ptr += strlen ("BitRate");
  101. if (isalnum (*ptr)) lineup (ptr,end);
  102. skipNonalnum (ptr,end);
  103. if (ptr >= end) break;
  104. *bitrate = atof (ptr);
  105. lineup (ptr,end);
  106. }
  107. else if (strncasecmp (ptr, "BlockSize", strlen ("BlockSize")) == 0)
  108. {
  109. ptr += strlen ("BlockSize");
  110. if (isalnum (*ptr)) lineup (ptr,end);
  111. skipNonalnum (ptr,end);
  112. if (ptr >= end) break;
  113. *bsize = atoi (ptr);
  114. lineup (ptr,end);
  115. }
  116. else if (strncasecmp (ptr, "DataLength", strlen ("DataLength")) == 0)
  117. {
  118. ptr += strlen ("DataLength");
  119. if (isalnum (*ptr)) lineup (ptr,end);
  120. skipNonalnum (ptr,end);
  121. if (ptr >= end) break;
  122. *datalen = atoi (ptr);
  123. lineup (ptr,end);
  124. }
  125. else if (strncasecmp (ptr, "Data", strlen ("Data")) == 0)
  126. {
  127. ptr += strlen ("Data=");
  128. len = *datalen;
  129. if (ptr >= end) break;
  130. dst = p = calloc (1, len+1);
  131. while (len >= 0)
  132. {
  133. *p++ = *ptr++;
  134. len --;
  135. }
  136. *data = dst;
  137. lineup (ptr,end);
  138. }
  139. else
  140. {
  141. lineup (ptr,end);
  142. }
  143. }
  144. fclose (in);
  145. if (buffer != NULL) free (buffer);
  146. return 0;
  147. }
  148. static inline void buildProgPath (char *buf, int len, char *md5)
  149. {
  150. snprintf (buf, len, "%s/%s/", PREFIX, PROG_PREFIX);
  151. strcat (buf, md5);
  152. }
  153. // Return 1 to indicate write available, return 0 to indicate now writable.
  154. static inline int newPListChannelFile (struct Channel *p)
  155. {
  156. struct stat stbuf;
  157. char buffer[MAX_LINE];
  158. struct LiveChannelInfo *pcinfo = p->pcinfo;
  159. if (pcinfo->numinput >= MAX_FILEINPUT)
  160. {
  161. PDEBUG ("Max file input has been reached, %s:%d.n", p->fname,pcinfo->numinput);
  162. return -1;
  163. }
  164. snprintf (buffer, MAX_LINE, "%s/%d", p->fname, pcinfo->numinput);
  165. if (stat (buffer, &stbuf) == 0 && (pcinfo->input[pcinfo->numinput] = fopen (buffer, "r")) != NULL)
  166. {
  167. pcinfo->maxID += stbuf.st_size / p->maxblocksize;
  168. pcinfo->numinput ++;
  169. return 0;
  170. }
  171. return -1;
  172. }
  173. static int init_prog (struct Channel *p)
  174. {
  175. int i;
  176. struct stat stbuf;
  177. char buffer[MAX_LINE];
  178. struct LiveChannelInfo *pcinfo = p->pcinfo;
  179. if (p->maxblocksize == 0) p->maxblocksize = DEFAULT_BLOCK;
  180. while ((i = newPListChannelFile (p)) == 0);
  181. pcinfo->max_queue = BLOCK_PER_FILE;
  182. snprintf (buffer, MAX_LINE, "%s/keysample", p->fname);
  183. if (stat (buffer, &stbuf) == 0)
  184. {
  185. if (!S_ISREG (stbuf.st_mode))
  186. {
  187. PDEBUG ("File %s exist and not a regular file", buffer);
  188. return -1;
  189. }
  190. }
  191. pcinfo->keyfile = fopen (buffer, "r");
  192. if (pcinfo->keyfile == NULL)
  193. {
  194. PDEBUG ("File %s can not be opened.n", buffer);
  195. return -1;
  196. }
  197. pcinfo->total = 0;
  198. pcinfo->isSave = 1;
  199. // timer_add (CurrentTime, (TimerFunc)send_spupdate, p, NULL);
  200. return 0;
  201. }
  202. static struct Channel *newProg (char *name, struct Session *source, char *cmd5, float bitrate, int maxblocksize)
  203. {
  204. int id;
  205. struct Channel *p;
  206. struct LiveChannelInfo *pcinfo;
  207. if (NumNewProg >= MAX_CHANNEL) return (struct Channel *)0;
  208. p = (struct Channel *)calloc (sizeof (struct Channel), 1);
  209. memcpy (p->channel_md5, cmd5, MD5_LEN);
  210. if (name) strncpy (p->channel_name, name, sizeof (p->channel_name));
  211. p->channel_md5[MD5_LEN] = 0;
  212. p->upsize = 0;
  213. p->downsize = 0;
  214. p->maxblocksize = maxblocksize;
  215. p->ctime = time (NULL);
  216. p->pcinfo = (struct LiveChannelInfo *)calloc (sizeof (struct LiveChannelInfo), 1);
  217. pcinfo = p->pcinfo;
  218. pcinfo->dataSource = source;
  219. pcinfo->bitrate = bitrate;
  220. buildProgPath (p->fname, CHNLURL_LEN, cmd5);
  221. if (init_prog (p) < 0)
  222. {
  223. PDEBUG ("newPlistChannel error for %p.", p);
  224. free_livechannel (p);
  225. free (pcinfo);
  226. free (p);
  227. return (struct Channel *)0;
  228. }
  229. id = hash_str (p->channel_md5, MD5_LEN);
  230. PDEBUG("newPlistChannel hash %.32s(fname=%s) to %d.n", p->channel_md5, p->fname, id);
  231. p->next = ProgramHash[id];
  232. ProgramHash[id] = p;
  233. p->lnext = ProgramList;
  234. ProgramList = p;
  235. NumNewProg ++;
  236. return p;
  237. }
  238. static struct Channel *add_prog (char *buffer, char *md5)
  239. {
  240. struct stat stbuf;
  241. struct Channel *pc=NULL;
  242. char *data=NULL, cname[MAX_DATA];
  243. float bitrate=0.0;
  244. int bsize=16384, dlen=0;
  245. if (stat (buffer, &stbuf) < 0) return NULL;
  246. if (!S_ISDIR (stbuf.st_mode))
  247. return NULL;
  248. else
  249. {
  250. strcat (buffer, "/config");
  251. if (read_prog_config (buffer, cname, sizeof(cname), &bitrate, &bsize, &dlen, &data) < 0)
  252. {
  253. PDEBUG ("Error in parse file %s.n", buffer);
  254. return NULL;
  255. }
  256. if ((pc=newProg (cname, NULL, md5, bitrate, bsize)) == NULL)
  257. {
  258. PDEBUG ("Cannot new plist Channel %sn", cname);
  259. free (data);
  260. return NULL;
  261. }
  262. pc->pcinfo->media = calloc (1, sizeof (struct MediaData));
  263. pc->pcinfo->media[0].start = 0;
  264. pc->pcinfo->media[0].len = pc->pcinfo->maxID;
  265. pc->pcinfo->media[0].dlen = dlen;
  266. pc->pcinfo->media[0].data = data;
  267. pc->pcinfo->cur_channel = pc->pcinfo->max_channel = 1;
  268. }
  269. return pc;
  270. }
  271. struct Channel *getProgrambymd5 (char *name, int len)
  272. {
  273. char buffer[MAX_DATA];
  274. struct Channel *result;
  275. if ((result = findProgram (name, len)) != NULL)
  276. return result;
  277. snprintf (buffer, MAX_DATA, "%s/%s/%s/", PREFIX, PROG_PREFIX, name);
  278. return add_prog (buffer, name);
  279. }
  280. int locateprog_by_id (struct Channel *pc, unsigned int id, char *buf, int max)
  281. {
  282. int i, pos, *msg;
  283. struct LiveChannelInfo *c = pc->pcinfo;
  284. if (c == NULL)
  285. {
  286. PDEBUG ("c is %p and id is (%d,%d).n", c, c->maxID, id);
  287. return -1;
  288. }
  289. i = id % c->maxID;
  290. pos = i / c->max_queue;
  291. i = i % c->max_queue;
  292. if (pc->maxblocksize + 2*sizeof(int) > max)
  293. {
  294. PDEBUG ("too small buffer %d for %d", max, pc->maxblocksize);
  295. return -2;
  296. }
  297. if (pos >= c->numinput || c->input[pos] == NULL)
  298. {
  299. PDEBUG ("file %d does not exist. (%d,%p)n", pos, c->numinput, c->input[pos]);
  300. return -1;
  301. }
  302. if (fseeko (c->input[pos], ((off_t)(i)) * pc->maxblocksize, SEEK_SET) != 0)
  303. {
  304. PDEBUG ("Fssek failed. (%d, %d, %d)n", pos, i, pc->maxblocksize);
  305. return -1;
  306. }
  307. if ((i=fread (buf+2*sizeof(int), 1, pc->maxblocksize, c->input[pos])) != pc->maxblocksize)
  308. {
  309. PDEBUG ("Fread failed. (%d, %d, %d)n", pos, i, pc->maxblocksize);
  310. return -1;
  311. }
  312. msg = (int *)buf;
  313. msg[0] = id;
  314. msg[1] = pc->maxblocksize;
  315. pc->upsize += msg[1];
  316. return msg[1];
  317. }
  318. inline void freeProgram (struct Channel *pc, void *p)
  319. {
  320. freeChannel (ProgramHash, &ProgramList, &NumNewProg, pc);
  321. }
  322. void freeAllProgram ()
  323. {
  324. apply_hash (ProgramHash, freeProgram, NULL);
  325. }