OSDN Git Service

2011/10/25 0:15:37
[nlite/nlite.git] / nlib / nlib_nicoLive.c
1
2
3 #include "nlib_include.h"
4
5
6
7 //NlibProperty nlibProperty;
8
9
10
11
12 static XML_Parser xmlParser;
13 static CRITICAL_SECTION playerStatusParserCs;
14 static INT_PTR res_from = 0;
15
16 static NicoLiveHeartBeatContainer heartBeatContainer;
17 static CRITICAL_SECTION heartBeatCs;
18
19 static DWORD heartBeatTime = 300000;
20
21 static BOOL heartBeatFlag = TRUE;
22
23
24 static DWORD keapALiveTime = 300000;
25
26 static BOOL keapALiveFlag = TRUE;
27
28
29 //
30 //\83}\83N\83\8d
31 //
32 #define XMLSPACE L" \t\r\n"
33
34 #define parseAttr(indexPtr,ans,ane,avs,ave)\
35         (ans) = (indexPtr);\
36         (ane) = wcspbrk((ans),XMLSPACE L"=");\
37         (avs) = wcsstr((ane),L"\"") + 1;\
38         (ave) = wcsstr((avs),L"\"");\
39         (indexPtr) = (ave) + 1
40
41 #define skipXMLSPACE(indexPtr)\
42         for(;(*(indexPtr)) == L' ' || (*(indexPtr)) == '\t' || (*(indexPtr)) == '\r' || (*(indexPtr)) == '\n';indexPtr++)
43
44 #define partString(ptr,start,end)\
45         ptr = start;\
46         end[0] = L'\0'
47
48
49 #define convertXMLTEXT(buf,basePtr,convPtr,endPtr)\
50         (buf) = (basePtr);\
51         for(;(basePtr) < (endPtr);(basePtr)++,(convPtr)++){\
52                 if(wcsncmp((basePtr),L"&amp;",wcslen(L"&amp;")) == 0){\
53                         (convPtr)[0] = L'&';\
54                         (basePtr) += wcslen(L"&amp;") - 1;\
55                 } else if(wcsncmp((basePtr),L"&lt;",wcslen(L"&lt;")) == 0){\
56                         (convPtr)[0] = L'<';\
57                         (basePtr) += wcslen(L"&lt;") - 1;\
58                 } else if(wcsncmp((basePtr),L"&gt;",wcslen(L"&gt;")) == 0){\
59                         (convPtr)[0] = L'>';\
60                         (basePtr) += wcslen(L"&gt;") - 1;\
61                 } else if(wcsncmp((basePtr),L"&quot;",wcslen(L"&quot;")) == 0){\
62                         (convPtr)[0] = L'\"';\
63                         (basePtr) += wcslen(L"&quot;") - 1;\
64                 } else if(wcsncmp((basePtr),L"&apos;",wcslen(L"&apos;")) == 0){\
65                         (convPtr)[0] = L'\'';\
66                         (basePtr) += wcslen(L"&apos;") - 1;\
67                 } else {\
68                         (convPtr)[0] = (basePtr)[0];\
69                 }\
70         }\
71         (convPtr)[0] = L'\0'
72
73
74
75 #define convertTEXT(buf,basePtr,convPtr,endPtr)\
76         (buf) = (convPtr);\
77         for(;(basePtr) < (endPtr);(basePtr)++){\
78                 switch(basePtr[0]){\
79                 case L'&':\
80                         strcpy((convPtr),"&amp;");\
81                         (convPtr) += strlen(convPtr);\
82                         break;\
83                 case L'<':\
84                         strcpy((convPtr),"&lt;");\
85                         (convPtr) += strlen(convPtr);\
86                         break;\
87                 case L'>':\
88                         strcpy((convPtr),"&gt;");\
89                         (convPtr) += strlen(convPtr);\
90                         break;\
91                 case L'\"':\
92                         strcpy((convPtr),"&quot;");\
93                         (convPtr) += strlen(convPtr);\
94                         break;\
95                 case L'\'':\
96                         strcpy((convPtr),"&apos;");\
97                         (convPtr) += strlen(convPtr);\
98                         break;\
99                 default:\
100                         WideCharToMultiByte(CP_UTF8,0,(basePtr),1,(convPtr),LENGTH_1024,(LPCSTR)NULL,(LPBOOL)NULL);\
101                         (convPtr) += strlen(convPtr);\
102                         break;\
103                 }\
104         }\
105         (convPtr)[0] = '\0'
106
107                         
108
109
110
111 #define getBaseVpos(server_time,base_time)      (((server_time) - (base_time)) * 100)
112
113 #define setMsec(mSec)\
114         timeBeginPeriod(1);\
115         (mSec) = timeGetTime();\
116         timeEndPeriod(1)
117
118 #define NicoLiveStream_setVpos(nl,attr)\
119         (nl).chatManager.baseVpos = getBaseVpos((wcstoul((attr),NULL,0)),((nl).playerStatus.stream.base_time));\
120         setMsec((nl).chatManager.commentStartTime)
121
122
123
124
125 //
126 //\83v\83\89\83C\83x\81[\83g\8aÖ\90\94
127 //
128
129 ///
130 ///\83v\83\8c\83C\83\84\81[\83X\83e\81[\83^\83X\8eæ\93¾
131 ///
132 static INLINE NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P pPlayerStatus,LPCWSTR liveNO,LPCWSTR userSession,HINTERNET hConnect);
133
134 ///
135 ///nicoLiveHistory\8eæ\93¾
136 ///
137 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect);
138
139
140
141
142
143 ///
144 ///\83v\83\8c\83C\83\84\81[\83X\83e\81[\83^\83X\83p\81[\83T\8f\89\8aú\89»
145 ///
146 static INLINE VOID Parser_Initialize();
147
148
149 ///
150 ///\83v\83\8c\83C\83\84\81[\83X\83e\81[\83^\83X\83p\81[\83T\8cã\8f\88\97\9d
151 ///
152 static INLINE VOID Parser_Finalize();
153
154
155 ///
156 ///\83v\83\8c\83C\83\84\81[\83X\83e\81[\83^\83X\83p\81[\83X\8f\88\97\9d
157 ///
158 static INLINE VOID XMLParse(LPVOID option,LPCSTR body,XML_StartElementHandler startElementEvent,XML_EndElementHandler endElementEvent,XML_CharacterDataHandler characterDataEvent);
159
160
161
162 ///
163 ///\83`\83\83\83b\83g\8eó\90M\83\8b\81[\83v\8aJ\8en\8aÖ\90\94
164 ///
165 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer);
166
167 ///
168 ///\83n\81[\83g\83r\81[\83g\91\97\90M\83\8b\81[\83v\8aÖ\90\94
169 ///
170 static unsigned int WINAPI  NicoLiveHeartBeatThread(void* lpBuffer);
171
172
173 ///
174 ///\83L\81[\83v\83A\83\89\83C\83u\91\97\90M\83\8b\81[\83v\8aÖ\90\94
175 ///
176 static unsigned int WINAPI  NicoLiveKeapALiveThread(void* lpBuffer);
177
178 ///
179 ///\83`\83\83\83b\83g\8eó\90M\83\8b\81[\83v\8aÖ\90\94
180 ///
181 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self);
182
183
184 ///
185 ///\83R\83\81\83\93\83g\89ð\90Í\8aÖ\90\94
186 ///
187 static VOID  NicoLiveParseComment(NicoLiveStream_P self,LPWSTR commentBuf,UINT_PTR endSize,LPWSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentCountSum,SIZE_T* commentBufSize);
188
189 static void NicoLiveError(void *buf);
190
191
192 ///
193 ///\83\\83P\83b\83g\8eæ\93¾\8aÖ\90\94
194 ///
195 static INLINE SOCKET GetConectedSocket(LPCWSTR nordName,LPCWSTR port,int socktype,int addr_famiry,int protocol);
196
197 BOOL Initialize_NicoLive(){
198
199
200
201         //\83p\81[\83T\82ð\8f\89\8aú\89»
202         Parser_Initialize();
203
204         //\83n\81[\83g\83r\81[\83g\83R\83\93\83e\83i\8f\89\8aú\89»
205         ZeroMemory(&heartBeatContainer,sizeof(heartBeatContainer));
206         heartBeatContainer.is_restrictSize = sizeof(WCHAR) * LENGTH_1024;
207         heartBeatContainer.is_restrictBuff = (LPWSTR)calloc(1,heartBeatContainer.is_restrictSize);
208         heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
209
210         heartBeatContainer.ticketSize = sizeof(WCHAR) * LENGTH_1024;
211         heartBeatContainer.ticketBuff = (LPWSTR)calloc(1,heartBeatContainer.ticketSize);
212         heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
213
214         InitializeCriticalSection(&heartBeatCs);
215
216
217         return TRUE;
218
219
220
221 }
222
223
224 extern BOOL Finalize_NicoLive(){
225
226
227         DeleteCriticalSection(&heartBeatCs);
228
229         //\83p\81[\83T\8cã\8f\88\97\9d
230         free(heartBeatContainer.is_restrictBuff);
231         free(heartBeatContainer.ticketBuff);
232
233
234         //\83v\83\8c\83C\83\84\81[\83X\83e\81[\83^\83X\83p\81[\83T\8cã\8f\88\97\9d
235         Parser_Finalize();
236
237
238
239
240
241
242
243 }
244
245
246 NicoLiveStream_P NicoLiveStream_new(){
247         //\90\90¬&\8f\89\8aú\89»
248         NicoLiveStream_P self = (NicoLiveStream_P)calloc(1,sizeof(NicoLiveStream));
249
250         self->chatManager.endEvent = WSACreateEvent();
251
252         self->chatManager.startEvent = WSACreateEvent();
253
254         self->chatManager.deleteEvent = WSACreateEvent();
255
256         self->chatManager.resetEvents[0] = WSACreateEvent();
257
258         self->chatManager.resetEvents[1] = WSACreateEvent();
259
260         self->chatManager.resetEvents[2] = WSACreateEvent();
261
262         self->chatManager.hRecvChatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveRecvChat,self,0,&self->chatManager.recvChatThreadID);
263
264         self->chatManager.hHeartBeatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveHeartBeatThread,self,0,&self->chatManager.heartBeatThreadID);
265
266         self->chatManager.hKeapALiveHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveKeapALiveThread,self,0,&self->chatManager.keapALiveThreadID);
267
268         dumpln(TEXT("size%d"),sizeof(NicoLiveStream));
269
270         
271
272         return self;
273 }
274
275
276
277 //
278 //\83j\83R\83j\83R\90\95ú\91\97\8aÖ\98A\8aÖ\90\94
279 ///////////////////////////////////////////////////
280
281 VOID NicoLiveStream_delete(NicoLiveStream_P* self){
282
283         NicoLiveStream_disConnect((*self));
284
285         WSASetEvent((*self)->chatManager.deleteEvent);
286
287         if(INVALID_HANDLE_VALUE  != (*self)->chatManager.hRecvChatHandle){
288                 WaitForSingleObject( (*self)->chatManager.hRecvChatHandle, INFINITE );
289         }
290
291         if(INVALID_HANDLE_VALUE != (*self)->chatManager.hHeartBeatHandle){
292
293                 WaitForSingleObject((*self)->chatManager.hHeartBeatHandle,INFINITE);
294         }
295
296         if(INVALID_HANDLE_VALUE != (*self)->chatManager.hKeapALiveHandle){
297
298                 WaitForSingleObject((*self)->chatManager.hKeapALiveHandle,INFINITE);
299
300         }
301
302         CloseHandle((*self)->chatManager.hRecvChatHandle);
303
304         CloseHandle((*self)->chatManager.hHeartBeatHandle);
305
306         CloseHandle((*self)->chatManager.hKeapALiveHandle);
307
308         //\8cã\8f\88\97\9d&\94j\8aü
309
310         WSACloseEvent((*self)->chatManager.endEvent);
311
312         WSACloseEvent((*self)->chatManager.startEvent);
313
314         WSACloseEvent((*self)->chatManager.deleteEvent);
315
316         WSACloseEvent((*self)->chatManager.resetEvents[0]);
317
318         WSACloseEvent((*self)->chatManager.resetEvents[1]);
319
320         WSACloseEvent((*self)->chatManager.resetEvents[2]);
321
322
323
324         //closesocket(self->chatManager.sock);
325
326
327
328
329         //nicoLiveStream_Finalize((**self));
330
331         free((*self));
332
333         (*self) = (NicoLiveStream_P)NULL;
334
335         return;
336 }
337
338
339 ///
340 ///\83n\81[\83g\83r\81[\83g\82Ì\8aÔ\8au\82ð\90Ý\92è\81i\83~\83\8a\95b)
341 ///
342 VOID SetHeartBeatMsec(DWORD msec){
343
344
345         heartBeatTime = msec;
346
347 }
348
349 ///
350 ///\83n\81[\83g\83r\81[\83g\82Ì\8aÔ\8au\82ð\8eæ\93¾(\83~\83\8a\95b)
351 ///
352 DWORD GetHeartBeatMsec(){
353
354         return heartBeatTime;
355
356
357 }
358
359 ///
360 ///\83n\81[\83g\83r\81[\83g\97L\8cø\81E\96³\8cø\90Ý\92è
361 ///
362 VOID SetHeartBeatFlag(BOOL flag){
363
364         heartBeatFlag = flag;
365
366 }
367
368
369 ///
370 ///\83n\81[\83g\83r\81[\83g\97L\8cø\83t\83\89\83O\8eæ\93¾
371 ///
372 BOOL GetHeartBeatFlag(){
373
374         return heartBeatFlag;
375
376
377 }
378
379
380 ///
381 ///\83L\81[\83v\83A\83\89\83C\83u\82Ì\8aÔ\8au\82ð\90Ý\92è(\83~\83\8a\95b)
382 ///
383 VOID SetKeapALiveMsec(DWORD msec){
384
385         keapALiveTime = msec;
386
387 }
388
389 ///
390 ///\83L\81[\83v\83A\83\89\83C\83u\82Ì\8aÔ\8au\82ð\8eæ\93¾(\83~\83\8a\95b)
391 ///
392 DWORD GetKeapALiveMsec(){
393
394         return keapALiveTime;
395
396 }
397
398
399 ///
400 ///\83L\81[\83v\83A\83\89\83C\83u\97L\8cø\81E\96³\8cø\90Ý\92è
401 ///
402 VOID SetKeapALiveFlag(BOOL flag){
403
404         keapALiveFlag = flag;
405 }
406
407
408 ///
409 ///\83L\81[\83v\83A\83\89\83C\83u\83t\83\89\83O\8eæ\93¾
410 ///
411 BOOL GetKeapALiveFlag(){
412
413         return keapALiveFlag;
414
415 }
416
417 VOID SetResFrom(INT_PTR res){
418
419         res_from = (-1) * res;
420
421 }
422
423 INT_PTR GetResFrom(){
424
425         return (-1) * res_from;
426 }
427
428 NLIB_RESULT NicoLiveStream_connect(NicoLiveStream_P self,NicoVideoAuth_P nicoVideoAuth,LPCWSTR url,NicoRecvCallBack callback,LPVOID option){
429
430 #define NICOLIVE_CONNECTIONSTREAM_COOKIE_COUNT          1
431 #define LIVENO_LENGTH                                                           LENGTH_NICOLIVEID
432
433         NLIB_RESULT rslt = NLIB_ERR_OK;
434
435
436
437
438
439
440
441         //url\82©\82ç\90Ú\91±\94Ô\8d\86\82ð\92\8a\8fo
442         LPCWSTR pInputLiveNo = url;
443         LPCWSTR psrech = wcsstr(url,L"http://");
444         LPCWSTR pInputLiveNoEnd;
445         WCHAR liveNo[LIVENO_LENGTH] = {0};
446         HINTERNET hWatchLiveNicVideo = NULL;
447
448         //\91O\82É\82Â\82È\82¢\82Å\82¢\82½\95ú\91\97\82ð\90Ø\92f
449         NicoLiveStream_disConnect(self);
450
451         if(psrech != NULL){
452
453                 psrech += 7;
454
455                 for(;psrech != NULL;psrech = wcsstr(psrech +1,L"/")){
456
457                         pInputLiveNo = psrech + 1;
458
459
460                 }
461         }
462
463         pInputLiveNoEnd = wcsstr(pInputLiveNo,L"?");
464
465         if(pInputLiveNoEnd == NULL){
466
467                 pInputLiveNoEnd = pInputLiveNo + wcslen(pInputLiveNo);
468
469         }
470
471         if(pInputLiveNo == NULL){
472
473                 rslt = NLIB_LIVENO_FAILED_INPUT;
474                 goto end;
475
476         }else if(pInputLiveNoEnd - pInputLiveNo + 2 >= LIVENO_LENGTH - 1){
477
478                 rslt = NLIB_LIVENO_FAILED_TOOBIG;
479                 goto end;
480
481         } else if((wcsncmp(pInputLiveNo,TEXT("lv"),2) == 0)||(( wcsncmp(pInputLiveNo,TEXT("co"),2) == 0) || (wcsncmp(pInputLiveNo,TEXT("ch"),2) == 0) )){
482
483
484                 wcsncpy(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
485
486
487         } else if(_wtoi(pInputLiveNo) != 0){
488
489                 wcscpy(liveNo,L"lv");
490                 wcsncat(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
491
492         } else {
493
494                 rslt = NLIB_LIVENO_FAILED_UNDEFEINE;
495                 goto end;
496
497
498         }
499
500
501
502
503
504         wcscpy(self->userSession,nicoVideoAuth->userSession);
505
506
507
508         //watch.live.nicovideo\82É\90Ú\91±
509         hWatchLiveNicVideo = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
510
511         if(hWatchLiveNicVideo == NULL){
512
513                 rslt = NLIB_ERR_WATCHLIVENICOVIDEO_FAILED_CONNECT;
514                 goto end;
515
516         }
517
518
519         //\83v\83\8c\83C\83\84\81[\83X\83e\81[\83^\83X\8eæ\93¾
520         rslt = GetPlayerStatus(&self->playerStatus,liveNo,self->userSession,hWatchLiveNicVideo);
521
522         if(rslt != NLIB_ERR_OK){
523
524                 goto end;
525         }
526
527         if(res_from > 0 || res_from < -1000 ){
528
529                 res_from = 0;
530         }
531
532         //\90\95ú\91\97\83I\83u\83W\83F\83N\83g\82É\8ae\88ø\90\94\82ð\90Ý\92è
533         self->res_from = res_from;
534         self->callBack = callback;
535         self->option = option;
536
537
538         WSASetEvent(self->chatManager.startEvent);
539
540         //nicoLiveHistory\82ð\8eæ\93¾(\95K\97v\82È\82µ\81H)
541         //GetNicoLiveHistory(self,hWatchLiveNicVideo);
542
543 end:
544         WinHttpCloseHandle(hWatchLiveNicVideo);
545         //freeChunkGlobal(chunk);
546
547         return rslt;
548 }
549
550
551 NLIB_RESULT NicoLiveStream_sendHeartBeat(NicoLiveStream_P self){
552
553         
554         NLIB_RESULT rslt = NLIB_ERR_OK;
555
556         if(self == NULL || self->playerStatus.error != NLIB_ERR_OK){
557
558                 rslt = NLIB_ERR_PLAYERSTATUS_ERROR;
559                 goto end;
560
561         }
562
563
564         {
565                 HINTERNET hWatchLiveNicoSession = NULL;
566                 HINTERNET hGetPlayerStatusRequest = NULL;
567                 ChunkMemory_P chunk = allocChunkGlobal();
568          
569                 LPWSTR objectName = (LPWSTR)chunk->buffer;
570                 LPWSTR indexPtr;
571                 LPWSTR sendBuffer = (LPWSTR)&objectName[LENGTH_4096];
572                 LPSTR recvBuffer;
573                 DWORD readSize;
574                 DWORD statusCode;
575                 DWORD statusCodeSize = sizeof(statusCode);
576
577                 hWatchLiveNicoSession = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
578
579                 wcscpy(objectName,L"/api/heartbeat?v=");
580                 indexPtr = objectName + wcslen(objectName);
581                 wcscpy(indexPtr,self->playerStatus.stream.id);
582                 wcscpy(sendBuffer,L"Cookie: ");
583                 indexPtr = sendBuffer + wcslen(sendBuffer);
584                 wcscpy(indexPtr,self->userSession);
585
586
587
588         
589
590                 hGetPlayerStatusRequest = WinHttpOpenRequest(hWatchLiveNicoSession,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
591
592                 if(WinHttpSendRequest(hGetPlayerStatusRequest,sendBuffer,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
593
594                         rslt = NLIB_ERR_FAILED_NETWORK;
595                         goto connectend;
596
597                 }
598
599                 if(WinHttpReceiveResponse(hGetPlayerStatusRequest,NULL) == FALSE){
600
601                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
602                         goto connectend;
603
604                 }
605
606
607                 if (WinHttpQueryHeaders(hGetPlayerStatusRequest,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
608                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
609                         goto connectend;
610                 }
611
612
613                 if (HTTP_STATUS_OK != statusCode){
614                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
615                         goto connectend;
616                 }
617
618
619                 recvBuffer = (LPSTR)sendBuffer;
620
621
622                 if(ReadHttpBody(hGetPlayerStatusRequest,(LPBYTE)recvBuffer,CHUNKMEMORY_MAXSIZE,&readSize) == FALSE){
623
624                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
625                         goto connectend;
626
627                 }
628
629                 {
630                         
631                         
632                         EnterCriticalSection(&heartBeatCs);
633
634                         XMLParse(&heartBeatContainer,recvBuffer,NicoLiveHeartBeat_ElementStartHandler,NicoLiveHeartBeat_ElementEndHandler,NicoLiveHeartBeat_CharacterDataHandler);
635
636                         self->chatManager.baseVpos = getBaseVpos(heartBeatContainer.heartBeat.time, self->playerStatus.stream.base_time);
637                         setMsec(self->chatManager.commentStartTime);
638
639                         self->callBack(NICOLIVE_EVENT_SEND_HEARTBEAT,self,self->option,(NICOLIVE_PARAM)&heartBeatContainer.heartBeat,(NICOLIVE_PARAM)NULL);
640
641                         ZeroMemory(&heartBeatContainer.heartBeat,sizeof(heartBeatContainer.heartBeat));
642
643                         ZeroMemory(heartBeatContainer.is_restrictBuff,heartBeatContainer.is_restrictSize);
644
645                         ZeroMemory(heartBeatContainer.ticketBuff,heartBeatContainer.ticketSize);
646
647                         heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
648
649                         heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
650
651                         LeaveCriticalSection(&heartBeatCs);
652
653
654                 }
655
656 connectend:
657                 freeChunkGlobal(chunk);
658                 WinHttpCloseHandle(hWatchLiveNicoSession);
659                 WinHttpCloseHandle(hGetPlayerStatusRequest);
660
661         }
662 end:
663         
664
665         return rslt;
666 }
667
668 VOID NicoLiveStream_disConnect(NicoLiveStream_P self){
669
670
671         WSAResetEvent(self->chatManager.startEvent);
672         WSASetEvent(self->chatManager.endEvent);
673
674         
675
676
677
678         WSAWaitForMultipleEvents(sizeof(self->chatManager.resetEvents) / sizeof(self->chatManager.resetEvents[0]),self->chatManager.resetEvents,TRUE,WSA_INFINITE,FALSE);
679
680         {
681
682                 WSAEVENT eventObject = self->chatManager.endEvent;
683                 WSAEVENT startObject = self->chatManager.startEvent;
684                 WSAEVENT deleteObject = self->chatManager.deleteEvent;
685                 HANDLE recvThread = self->chatManager.hRecvChatHandle;
686                 DWORD recvThreadID = self->chatManager.recvChatThreadID;
687
688                 //nicoLiveStream_Initialize(*self);
689                 ZeroMemory(self,sizeof(*self));
690                 WSAResetEvent(eventObject);
691                 self->chatManager.hRecvChatHandle = recvThread;
692                 self->chatManager.recvChatThreadID = recvThreadID;
693                 self->chatManager.endEvent = eventObject;
694                 self->chatManager.startEvent = startObject;
695                 self->chatManager.deleteEvent = deleteObject;
696         }
697
698
699
700
701
702
703
704
705         return;
706
707
708
709 }
710
711
712 #define NICOLIVE_SENDCHATBUFLEN                 LENGTH_4096
713 #define NICOLIVE_SENDFORMAT                             "<chat thread=\"%d\" ticket=\"%S\"  postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
714
715 NLIB_RESULT NicoLiveStream_sendChat(NicoLiveStream_P self,LPCWSTR chatbuf,LPCWSTR *mail,LPCWSTR *extends){
716
717
718
719         ChunkMemory_P chunkMemory = allocChunkGlobal();
720
721         LPSTR postKey;
722         LPSTR postKeyBuf = (LPSTR)chunkMemory->buffer;
723         LPWSTR postKeyReqBuf = (LPWSTR)&postKeyBuf[NICOLIVE_SENDCHATBUFLEN];
724         LPWSTR cookieBuf = &postKeyReqBuf[NICOLIVE_SENDCHATBUFLEN];
725         DWORD statusCode;
726         DWORD statusCodeSize = sizeof(statusCode);
727         DWORD readSize;
728
729         HINTERNET hWatchLiveNicoVideo = NULL;
730         HINTERNET hGetPostKeySession = NULL;
731         NLIB_RESULT rslt = NLIB_ERR_OK;
732
733         if(chatbuf == NULL || wcslen(chatbuf) >= LENGTH_1024){
734
735                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
736                 goto end;
737
738         }
739
740
741         //postkey\8eæ\93¾
742         _swprintf(postKeyReqBuf,L"api/getpostkey?thread=%u&block_no=%u",self->playerStatus.ms.thread,self->chatManager.commentCount / 100);
743
744         hWatchLiveNicoVideo = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
745         hGetPostKeySession = WinHttpOpenRequest(hWatchLiveNicoVideo,L"GET",postKeyReqBuf,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
746
747
748         //_swprintf(cookieBuf,L"Cookie: %s; %s",self->userSession,self->nicoLiveHistory);
749         _swprintf(cookieBuf,L"Cookie: %s",self->userSession);
750
751         if(WinHttpSendRequest(hGetPostKeySession,cookieBuf,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
752
753                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
754                 goto end;
755
756         }
757
758
759         if(WinHttpReceiveResponse(hGetPostKeySession,NULL) == FALSE){
760
761                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
762                 goto end;
763
764         }
765
766
767         if (WinHttpQueryHeaders(hGetPostKeySession,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
768                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
769                 goto end;
770         }
771
772
773         if (HTTP_STATUS_OK != statusCode){
774                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
775                 goto end;
776         }
777
778
779
780
781
782         if(ReadHttpBody(hGetPostKeySession,(LPBYTE)postKeyBuf,CHUNKMEMORY_MAXSIZE,&readSize) == FALSE){
783
784                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
785                 goto end;
786
787         }
788         postKeyBuf[readSize] = '\0';
789         postKey = strstr(postKeyBuf,"=") + 1;
790
791
792         {
793                 LPSTR buffer = (LPSTR)&cookieBuf[NICOLIVE_SENDCHATBUFLEN * 4];
794                 LPSTR indexPtr;
795                 LPSTR mailBuf;
796                 LPSTR extendBuf;
797                 
798                 //mail\83R\83}\83\93\83h\8dì\90¬
799                 if(mail == NULL){
800
801                         mailBuf = "";
802
803                 } else {
804                         INT_PTR len;
805                         mailBuf = (LPSTR)postKeyReqBuf;
806                         indexPtr = mailBuf;
807                         strcpy(indexPtr,"mail=\"");
808                         indexPtr += strlen(indexPtr);
809
810                         len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
811                         if(GetLenToMB(CP_UTF8,mail[0]) >= len){
812                                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
813                                 goto end;
814
815                         }
816
817                         WideToMB(CP_UTF8,mail[0],indexPtr,len);
818                         indexPtr += strlen(indexPtr);
819
820
821                         for(mail++;mail[0] != NULL;mail++){
822
823                                 indexPtr[0] = ' ';
824                                 indexPtr++;
825
826                                 len =  NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
827
828                                 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
829                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
830                                         goto end;
831
832                                 }
833
834                                 WideToMB(CP_UTF8,mail[0],indexPtr,len);
835                                 indexPtr += strlen(indexPtr);
836
837                         }
838                         strcpy(indexPtr,"\"");
839
840
841
842
843                 }
844
845                 //\8ag\92£\91®\90«\8dì\90¬
846                 if(extends == NULL){
847
848                         extendBuf = "";
849
850                 } else {
851                         INT_PTR len;
852                         extendBuf  =(LPSTR)cookieBuf;
853                         indexPtr = extendBuf;
854
855
856                         len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
857
858                         if(GetLenToMB(CP_UTF8,extends[0]) >= len){
859                                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
860                                 goto end;
861
862                         }
863                         WideToMB(CP_UTF8,extends[0],indexPtr,len);
864
865                         indexPtr += strlen(indexPtr);
866
867                         strcpy(indexPtr,"=\"");
868                         indexPtr += strlen(indexPtr);
869
870
871                         len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
872
873                         if(GetLenToMB(CP_UTF8,extends[1]) >= len){
874                                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
875                                 goto end;
876
877                         }
878                         WideToMB(CP_UTF8,extends[1],indexPtr,len);
879
880
881                         for(extends+= 2;extends[0] != NULL;extends+=2){
882
883                                 indexPtr[0] = ' ';
884                                 indexPtr++;
885
886                                 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
887
888                                 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
889                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
890                                         goto end;
891
892                                 }
893                                 WideToMB(CP_UTF8,extends[0],indexPtr,len);
894
895                                 indexPtr += strlen(indexPtr);
896
897                                 indexPtr[0] = '=';
898                                 indexPtr++;
899
900
901                                 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
902
903                                 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
904                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
905                                         goto end;
906
907                                 }
908                                 WideToMB(CP_UTF8,extends[1],indexPtr,len);
909
910
911
912                         }
913                         indexPtr += strlen(indexPtr);
914                         strcpy(indexPtr,"\"");
915
916
917
918                 }
919
920                 //\83`\83\83\83b\83g\91\97\90M\83R\83\81\83\93\83g\8dì\90¬
921                 {
922                         indexPtr = buffer;
923                         //\96{\93\96\82Í\82±\82¤\82µ\82½\82¢:"<chat thread=\"%d\" ticket=\"%S\"  postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
924                         strcpy(indexPtr,"<chat thread=\"");
925                         indexPtr += strlen(indexPtr);
926                         sprintf(indexPtr,"%u",self->playerStatus.ms.thread);
927                         indexPtr += strlen(indexPtr);
928                         strcpy(indexPtr,"\" ticket=\"");
929                         indexPtr += strlen(indexPtr);
930                         WideToMB(CP_UTF8,self->ticket,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
931                         indexPtr += strlen(indexPtr);
932                         strcpy(indexPtr,"\"  postkey=\"");
933                         indexPtr += strlen(indexPtr);
934                         strcpy(indexPtr,postKey);
935                         indexPtr += strlen(indexPtr);
936                         strcpy(indexPtr,"\" user_id=\"");
937                         indexPtr += strlen(indexPtr);
938                         WideToMB(CP_UTF8,self->playerStatus.user.user_id,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
939                         indexPtr += strlen(indexPtr);
940                         strcpy(indexPtr,"\" premium=\"");
941                         indexPtr += strlen(indexPtr);
942                         sprintf(indexPtr,"%u",self->playerStatus.user.is_premium);
943                         indexPtr += strlen(indexPtr);
944                         strcpy(indexPtr,"\" locale=\"");
945                         indexPtr += strlen(indexPtr);
946                         WideToMB(CP_UTF8,self->playerStatus.user.userDomain,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
947                         indexPtr += strlen(indexPtr);
948                         strcpy(indexPtr,"\" vpos=\"");
949                         indexPtr += strlen(indexPtr);
950                         
951                         
952                         timeBeginPeriod(1);
953                         sprintf(indexPtr,"%u",(self->chatManager.baseVpos + ((timeGetTime() - self->chatManager.commentStartTime) / 10)));
954                         timeEndPeriod(1);
955                         
956                         indexPtr += strlen(indexPtr);
957                         strcpy(indexPtr,"\"");
958                         indexPtr += strlen(indexPtr);
959
960                         if(strlen(mailBuf) > 0 && strlen(extendBuf) > 0){
961
962                                 indexPtr[0] = ' ';
963                                 indexPtr++;
964                                 strcpy(indexPtr,mailBuf);
965                                 indexPtr += strlen(indexPtr);
966
967                                 indexPtr[0] = ' ';
968                                 indexPtr++;
969
970                                 strcpy(indexPtr,extendBuf);
971                                 indexPtr += strlen(indexPtr);
972
973
974                         } else if(strlen(mailBuf) > 0){
975                                 indexPtr[0] = ' ';
976                                 indexPtr++;
977                                 strcpy(indexPtr,mailBuf);
978                                 indexPtr += strlen(indexPtr);
979
980                         } else if(strlen(extendBuf) > 0){
981                                 indexPtr[0] = ' ';
982                                 indexPtr++;
983                                 strcpy(indexPtr,extendBuf);
984                                 indexPtr += strlen(indexPtr);
985                         }
986                         strcpy(indexPtr,">");
987                         indexPtr += strlen(indexPtr);
988                         {
989                                 LPCWSTR endPtr= chatbuf + wcslen(chatbuf);
990                                 convertTEXT(indexPtr,chatbuf,indexPtr,endPtr);
991                                 //WideToMB(CP_UTF8,chatbuf,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
992                                 //indexPtr += strlen(indexPtr);
993                         }
994                         strcpy(indexPtr,"</chat>");
995
996
997
998                         {
999                                 INT_PTR sendLen = 0;
1000                                 INT_PTR sentLen = 0;
1001                                 INT_PTR max = strlen(buffer) + 1;
1002
1003                                 do{
1004                                         sendLen = send(self->chatManager.sock,buffer,max - sentLen,0);
1005                                         sentLen += sendLen;
1006                                 } while(sendLen > 0);
1007
1008                         }
1009                 }
1010
1011
1012         }
1013
1014
1015
1016
1017 end:
1018
1019         WinHttpCloseHandle(hGetPostKeySession);
1020         WinHttpCloseHandle(hWatchLiveNicoVideo);
1021
1022         return rslt;
1023
1024 }
1025
1026
1027
1028
1029
1030
1031
1032 //
1033 //\83C\83\93\83\89\83C\83\93\8aÖ\90\94
1034 //
1035
1036
1037
1038 NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P self,LPCWSTR liveNo,LPCWSTR userSession,HINTERNET hConnect){
1039
1040         NLIB_RESULT rslt = NLIB_ERR_OK;
1041
1042         HINTERNET hWatchLiveNicoSession = NULL;
1043         HINTERNET hGetPlayerStatusRequest = NULL;
1044         ChunkMemory_P chunkMemory = (ChunkMemory_P)NULL;
1045         LPVOID buffer;
1046         LPWSTR sendBuffer;
1047         LPSTR recvBuffer;
1048         DWORD readSize;
1049         DWORD statusCode;
1050         DWORD statusCodeSize = sizeof(statusCode);
1051
1052 #define GETPLAYERSTATUS_OBJECTNAME_LENGTH               LENGTH_256
1053
1054         WCHAR objectName[GETPLAYERSTATUS_OBJECTNAME_LENGTH] = {L"api/getplayerstatus?v="};
1055         const SIZE_T objectNameLen = wcslen(objectName);
1056         LPWSTR liveNoTmp = &objectName[objectNameLen];
1057
1058         if(wcslen(liveNo) > GETPLAYERSTATUS_OBJECTNAME_LENGTH - objectNameLen - 1){
1059
1060                 rslt = NLIB_LIVENO_FAILED_TOOBIG;
1061                 goto end;
1062
1063         } else if(wcslen(userSession) > LENGTH_4096){
1064
1065                 rslt = NLIB_USERSESSION_FAILED_TOOBIG;
1066                 goto end;
1067
1068         }
1069
1070         chunkMemory = allocChunkGlobal();
1071         buffer = getBufChunk(chunkMemory);
1072         sendBuffer = (LPWSTR)buffer;
1073         wcscpy(sendBuffer,L"Cookie: ");
1074         wcscat(sendBuffer,userSession);
1075
1076
1077         wcscpy(liveNoTmp,liveNo);
1078
1079         if(hConnect == NULL){
1080                 hWatchLiveNicoSession = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
1081         } else {
1082
1083                 hWatchLiveNicoSession = hConnect;
1084
1085         }
1086
1087         hGetPlayerStatusRequest = WinHttpOpenRequest(hWatchLiveNicoSession,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1088
1089         if(WinHttpSendRequest(hGetPlayerStatusRequest,sendBuffer,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1090
1091                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1092                 goto end;
1093
1094         }
1095
1096         if(WinHttpReceiveResponse(hGetPlayerStatusRequest,NULL) == FALSE){
1097
1098                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1099                 goto end;
1100
1101         }
1102
1103
1104         if (WinHttpQueryHeaders(hGetPlayerStatusRequest,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1105                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1106                 goto end;
1107         }
1108
1109
1110         if (HTTP_STATUS_OK != statusCode){
1111                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1112                 goto end;
1113         }
1114
1115
1116         recvBuffer = (LPSTR)sendBuffer;
1117
1118
1119         if(ReadHttpBody(hGetPlayerStatusRequest,(LPBYTE)recvBuffer,CHUNKMEMORY_MAXSIZE,&readSize) == FALSE){
1120
1121                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1122                 goto end;
1123
1124         }
1125
1126         recvBuffer[readSize] = '\0';
1127
1128         recvBuffer = strstr(recvBuffer,"<");
1129
1130         dumpln_mb(CP_UTF8,"%s",recvBuffer);
1131
1132
1133         XMLParse(self,recvBuffer,NPlayerStatus_ElementStartHandler,NPlayerStatus_ElementEndHandler,NPlayerStatus_CharacterDataHandler);
1134         rslt = self->error;
1135         if(rslt != NLIB_ERR_OK){
1136
1137                 goto end;
1138         }
1139
1140
1141 end:
1142
1143         freeChunkGlobal(chunkMemory);
1144         WinHttpCloseHandle(hGetPlayerStatusRequest);
1145
1146         //hConnect\82ªNULL\8ew\92è\82Å\93n\82³\82ê\82½\8fê\8d\87\81A\82±\82Ì\8aÖ\90\94\82Å\83n\83\93\83h\83\8b\82ð\90\90¬\82µ\82½\82Ì\82Å\95Â\82\82é
1147         if(hConnect == NULL){
1148                 WinHttpCloseHandle(hWatchLiveNicoSession);
1149         }
1150
1151         return rslt;
1152
1153 }
1154
1155
1156 #define GETNICOLIVEHIS_OBJNAMELENGTH    LENGTH_256
1157 #define GETNICOLIVEHIS_COOKIELENGTH             LENGTH_512
1158
1159 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect){
1160
1161         NLIB_RESULT rslt = NLIB_ERR_OK;
1162
1163         HINTERNET hNicoVideoConnect = NULL;
1164         HINTERNET hStreamBrowse = NULL;
1165
1166
1167         WCHAR objectName[GETNICOLIVEHIS_OBJNAMELENGTH] = {L"/watch/"};
1168         WCHAR cookie[GETNICOLIVEHIS_COOKIELENGTH] = {L"Cookie: "};
1169         DWORD statusCode;
1170         DWORD statusCodeSize = sizeof(statusCode);
1171         ChunkMemory_P chunkMemory = allocChunkGlobal();
1172         DWORD chunkSize = CHUNKMEMORY_MAXSIZE;
1173
1174
1175         LPWSTR buffer = (LPWSTR)chunkMemory->buffer;
1176
1177
1178
1179         if((GETNICOLIVEHIS_OBJNAMELENGTH - wcslen(objectName) <= wcslen(self->playerStatus.stream.id)) || GETNICOLIVEHIS_COOKIELENGTH - wcslen(cookie) <= wcslen(self->userSession)){
1180
1181                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1182                 goto end;
1183         } 
1184
1185         wcscat(objectName,self->playerStatus.stream.id);
1186         wcscat(cookie,self->userSession);
1187
1188         if(hConnect == NULL){
1189
1190                 hNicoVideoConnect =     WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
1191
1192         } else {
1193
1194                 hNicoVideoConnect = hConnect;
1195
1196         }
1197
1198         hStreamBrowse = WinHttpOpenRequest(hNicoVideoConnect,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1199
1200
1201
1202
1203         if(WinHttpSendRequest(hStreamBrowse,cookie,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1204
1205                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1206                 goto end;
1207
1208         }
1209
1210         if(WinHttpReceiveResponse(hStreamBrowse,NULL) == FALSE){
1211
1212                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1213                 goto end;
1214
1215         }
1216
1217         if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1218                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1219                 goto end;
1220         }
1221
1222
1223         if (HTTP_STATUS_OK != statusCode){
1224                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1225                 goto end;
1226         }
1227
1228
1229
1230         if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_SET_COOKIE,WINHTTP_HEADER_NAME_BY_INDEX,buffer,&chunkSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1231                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1232                 goto end;
1233         }
1234
1235         {
1236                 LPWSTR start =wcsstr(buffer,L"nicolivehistory=");
1237
1238                 LPWSTR end = wcsstr(start,L";");
1239
1240                 UINT_PTR length = end - start;
1241
1242                 if(length >= sizeof(self->nicoLiveHistory)){
1243                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1244                         goto end;
1245
1246                 }
1247
1248                 wcsncpy(self->nicoLiveHistory,start,length);
1249                 self->nicoLiveHistory[length] = L'\0';
1250
1251         }
1252 end:
1253         freeChunkGlobal(chunkMemory);
1254         WinHttpCloseHandle(hStreamBrowse);
1255
1256         if(hConnect == NULL){
1257
1258                 WinHttpCloseHandle(hNicoVideoConnect);
1259
1260         }
1261
1262
1263         return rslt;
1264
1265
1266
1267 }
1268
1269
1270
1271
1272 static INLINE VOID Parser_Initialize(){
1273
1274
1275         xmlParser = XML_ParserCreate((const XML_Char*)NULL);
1276
1277         check(xmlParser,TEXT("\83p\81[\83T\8f\89\8aú\89»\82É\8e¸\94s\82µ\82Ü\82µ\82½"));
1278
1279
1280
1281         InitializeCriticalSection(&playerStatusParserCs);
1282
1283 }
1284
1285 static INLINE VOID Parser_Finalize(){
1286
1287
1288         XML_ParserFree(xmlParser);
1289
1290         DeleteCriticalSection(&playerStatusParserCs);
1291
1292
1293 }
1294
1295 static INLINE VOID XMLParse(LPVOID option,LPCSTR body,XML_StartElementHandler startElementEvent,XML_EndElementHandler endElementEvent,XML_CharacterDataHandler characterDataEvent){
1296
1297         UserDataContainer userDataContainer;
1298         userDataContainer.nord = 0;
1299         userDataContainer.userData = option;
1300
1301
1302         EnterCriticalSection(&playerStatusParserCs);
1303
1304         //\91®\90«\90Ý\92è
1305         XML_SetElementHandler(xmlParser,startElementEvent,endElementEvent);
1306         XML_SetCharacterDataHandler(xmlParser,characterDataEvent);
1307         XML_SetUserData(xmlParser,&userDataContainer);
1308
1309         //\89ð\90Í
1310         XML_Parse(xmlParser,body,strlen(body),TRUE);
1311
1312         //\83\8a\83Z\83b\83g
1313         XML_ParserReset(xmlParser,(const XML_Char*)NULL);
1314
1315         LeaveCriticalSection(&playerStatusParserCs);
1316
1317
1318 }
1319
1320 static unsigned int WINAPI  NicoLiveKeapALiveThread(void* lpBuffer){
1321
1322         unsigned int rslt = 0;
1323
1324         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1325
1326         WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent};   //\83C\83x\83\93\83g\94z\97ñ
1327         DWORD dwResult;                                                                                                                                                                                                 //\83C\83x\83\93\83g\8eó\90M\8c\8b\89Ê
1328         DWORD endResult;
1329
1330         while(TRUE){
1331
1332                 WSASetEvent(self->chatManager.resetEvents[2]);
1333
1334                 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1335
1336
1337                 //\83G\83\89\81[\82Ì\8fê\8d\87
1338                 if(dwResult == WSA_WAIT_FAILED){
1339
1340                         goto err;
1341                 }
1342
1343
1344                 switch(dwResult - WSA_WAIT_EVENT_0){
1345
1346                 case 0:
1347
1348                         goto end;
1349
1350                 case 1:
1351                         break;
1352
1353                 case 2:
1354                         continue;
1355
1356                 default:
1357
1358                         goto err;
1359
1360                 }
1361
1362                 while(TRUE){
1363                         endResult = WSAWaitForMultipleEvents(1,&self->chatManager.endEvent,FALSE,keapALiveTime,FALSE);
1364
1365                         if(endResult == WSA_WAIT_TIMEOUT){
1366
1367                                 if(keapALiveFlag){
1368                                         LPCWSTR mail[2] = {L"184",NULL};
1369                                         NicoLiveStream_sendChat(self,L"/keapalive",mail,NULL);
1370                                 }
1371                         } else if(endResult - WSA_WAIT_EVENT_0 == 0){
1372
1373                                 break;;
1374
1375                         } else {
1376
1377                                 goto err;
1378                         }
1379                 }
1380
1381
1382         }
1383
1384 err:
1385         _beginthread(NicoLiveError,0,self);
1386
1387 end:
1388
1389         _endthreadex(rslt);
1390
1391         return rslt;
1392 }
1393
1394 static unsigned int WINAPI  NicoLiveHeartBeatThread(void* lpBuffer){
1395
1396         unsigned int rslt = 0;
1397
1398         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1399
1400         WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent};   //\83C\83x\83\93\83g\94z\97ñ
1401         DWORD dwResult;                                                                                                                                                                                                 //\83C\83x\83\93\83g\8eó\90M\8c\8b\89Ê
1402         DWORD endResult;
1403
1404         while(TRUE){
1405
1406                 WSASetEvent(self->chatManager.resetEvents[1]);
1407
1408                 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1409
1410
1411                 //\83G\83\89\81[\82Ì\8fê\8d\87
1412                 if(dwResult == WSA_WAIT_FAILED){
1413
1414                         goto err;
1415                 }
1416
1417
1418                 switch(dwResult - WSA_WAIT_EVENT_0){
1419
1420                 case 0:
1421
1422                         goto end;
1423
1424                 case 1:
1425                         break;
1426
1427                 case 2:
1428                         continue;
1429
1430                 default:
1431
1432                         goto err;
1433
1434                 }
1435
1436                 while(TRUE){
1437                         endResult = WSAWaitForMultipleEvents(1,&self->chatManager.endEvent,FALSE,heartBeatTime,FALSE);
1438
1439                         if(endResult == WSA_WAIT_TIMEOUT){
1440
1441                                 if(heartBeatFlag){
1442                                         NicoLiveStream_sendHeartBeat(self);
1443                                 }
1444                         } else if(endResult - WSA_WAIT_EVENT_0 == 0){
1445
1446                                 break;;
1447
1448                         } else {
1449
1450                                 goto err;
1451                         }
1452                 }
1453
1454
1455         }
1456
1457 err:
1458         _beginthread(NicoLiveError,0,self);
1459
1460 end:
1461
1462         _endthreadex(rslt);
1463
1464         return rslt;
1465 }
1466
1467
1468 #define NICOLIVE_RECEVE_CHAT_LENGTH     LENGTH_2048
1469 #define NICOLIVE_REQUEST_CHAT_LENGTH    LENGTH_256
1470 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer){
1471
1472
1473         unsigned int rslt = 0;
1474
1475         //LPWSTR user_id = NULL;
1476         //LPWSTR name = NULL;
1477         //LPWSTR chatBuf = NULL;
1478
1479
1480
1481         CHAR requestChat[NICOLIVE_REQUEST_CHAT_LENGTH];                                                                                                                                 //\91\97\90M\93d\95\97p\83o\83b\83t\83@
1482         LPCSTR sendFormat = "<thread thread=\"%u\" res_from=\"%d\" version=\"20061206\" />";                                                    //\91\97\90M\93d\95\83t\83H\81[\83}\83b\83g
1483         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;                                                                                                                             //\83j\83R\90\95ú\91\97\83I\83u\83W\83F\83N\83g
1484         INT_PTR sendLen;                                                                                                                                                                                                //\91\97\90M\97p\95\8e\9a\90\94
1485         INT_PTR sentLen;                                                                                                                                                                                                //\91\97\90M\8dÏ\82Ý\95\8e\9a\90\94
1486         WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent};   //\83C\83x\83\93\83g\94z\97ñ
1487         DWORD dwResult;                                                                                                                                                                                                 //\83C\83x\83\93\83g\8eó\90M\8c\8b\89Ê
1488
1489         
1490
1491         while(TRUE){
1492
1493                 WSASetEvent(self->chatManager.resetEvents[0]);
1494
1495                 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1496
1497
1498                 //\83G\83\89\81[\82Ì\8fê\8d\87
1499                 if(dwResult == WSA_WAIT_FAILED){
1500
1501                         goto err;
1502                 }
1503
1504
1505                 switch(dwResult - WSA_WAIT_EVENT_0){
1506
1507                 case 0:
1508
1509                         goto end;
1510
1511                 case 1:
1512                         break;
1513
1514                 case 2:
1515                         continue;
1516
1517                 default:
1518
1519                         goto err;
1520
1521                 }
1522
1523
1524                 sendLen = 0;
1525                 sentLen = 0;
1526
1527                 //\83\\83P\83b\83g\82Ì\90Ý\92è
1528                 self->chatManager.sock = GetConectedSocket(self->playerStatus.ms.addr,self->playerStatus.ms.port,SOCK_STREAM,AF_INET,IPPROTO_TCP);
1529
1530
1531                 //\83R\83\81\83\93\83g\8eó\90M\8aJ\8en\82Ì\89º\8f\80\94õ
1532                 if(self->chatManager.sock == INVALID_SOCKET){
1533                         self->error = NLIB_ERR_FAILED_NETWORK;
1534                         goto err;
1535                 }
1536
1537
1538
1539
1540
1541
1542                 if(NICOLIVE_REQUEST_CHAT_LENGTH <= _scprintf(sendFormat,self->playerStatus.ms.thread,self->res_from)){
1543
1544                         self->error = NLIB_ERR_BUFFER_TOOLITTLE;
1545                         rslt = -1;
1546                         goto err;
1547
1548
1549                 }
1550
1551                 sprintf(requestChat,sendFormat,self->playerStatus.ms.thread,self->res_from);
1552
1553
1554                 //
1555                 //\83R\83\81\83\93\83g\8eó\90M\97v\8b\81\91\97\90M\8f\88\97\9d
1556                 //
1557                 {
1558                         int len;
1559                         sendLen = strlen(requestChat) + 1;
1560                         do{
1561                                 len = send(self->chatManager.sock,requestChat,sendLen,0);
1562                                 if(len == SOCKET_ERROR){
1563                                         self->error = NLIB_ERR_FAILED_NETWORK;
1564                                         rslt = -1;
1565
1566                                         goto err;
1567
1568                                 }
1569
1570                                 sentLen = len;
1571                         }while(sentLen < sendLen);
1572                 }
1573
1574
1575                 if(NicoLiveRecvChatLoop(self) == FALSE){
1576                         goto err;
1577                 }
1578         }
1579
1580
1581
1582
1583 err:
1584
1585         _beginthread(NicoLiveError,0,self);
1586
1587 end:
1588
1589
1590
1591         closesocket(self->chatManager.sock);
1592         _endthreadex(rslt);
1593
1594         return rslt;
1595
1596
1597
1598
1599
1600 }
1601
1602
1603 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self){
1604
1605
1606         //
1607         //\83R\83\81\83\93\83g\8eó\90M\8f\88\97\9d
1608         //
1609         BOOL rslt = TRUE;                                                                               //\8c\8b\89Ê
1610         LPWSTR commentBuf = NULL;                                                               //\83R\83\81\83\93\83g\83o\83b\83t\83@
1611         LPWSTR* mailCountBuf = NULL;                                                    //\83\81\81[\83\8b\83|\83C\83\93\83^\83o\83b\83t\83@
1612         INT_PTR recevedLen;                                                                             //\8eó\90M\95\8e\9a\97ñ\92·
1613         INT_PTR messageBufLen;                                                                  //\83o\83b\83t\83@\92·
1614
1615
1616
1617         WSAEVENT hEventArray[2];                                                                //\8eó\90M\81E\90Ø\92f\82ð\8c\9f\92m\82·\82é\83C\83x\83\93\83g\83I\83u\83W\83F\83N\83g\82Ì\94z\97ñ
1618         WSANETWORKEVENTS netEvents;                                                             //\83l\83b\83g\83\8f\81[\83N\83C\83x\83\93\83g
1619         DWORD dwResult;                                                                                 //\83C\83x\83\93\83g\82ª\83E\83F\83C\83g\8aÖ\90\94\82Ì\8c\8b\89Ê\82ð\8ai\94[\82·\82é\95Ï\90\94
1620
1621
1622         SIZE_T commentBufSize = sizeof(WCHAR) * LENGTH_2048;    //\83R\83\81\83\93\83g\83o\83b\83t\83@\92·
1623         SIZE_T mailCountBufSize = sizeof(LPWSTR) * LENGTH_256;  //\83\81\81[\83\8b\82Ì\83|\83C\83\93\83^\97p\83o\83b\83t\83@\92·
1624
1625
1626
1627
1628
1629         SIZE_T commentCountSum = 0;                                                             //\83R\83\81\83\93\83g\83J\83E\83\93\83g                              
1630         WSAEVENT hRecvEvent = NULL;
1631
1632         //\8eó\90M\8f\80\94õ\8f\88\97\9d
1633         hRecvEvent = WSACreateEvent();
1634         self->chatManager.recvBuf[0] = '\0';
1635         WSAEventSelect(self->chatManager.sock, hRecvEvent, FD_READ | FD_CLOSE);
1636         hEventArray[0] = hRecvEvent;
1637         hEventArray[1] = self->chatManager.endEvent;
1638
1639         commentBuf = (LPWSTR)malloc(commentBufSize);
1640         mailCountBuf = (LPWSTR*)malloc(mailCountBufSize);
1641
1642         //\90Ø\92f\82³\82ê\82é\82Ü\82Å\83\8b\81[\83v
1643         while(1){
1644
1645
1646
1647                 //\91O\82Ì\83R\83\81\83\93\83g\8eó\90M\8e\9e\82É\97]\82Á\82½\95\8e\9a\97ñ\82Ì\92·\82³\82ð\92²\82×\82é
1648                 messageBufLen = strlen(self->chatManager.recvBuf);
1649
1650                 //\8eó\90M\82©\8fI\97¹\83C\83x\83\93\83g\82ð\8c\9f\92m\82·\82é\82Ü\82Å\91Ò\8b@
1651                 dwResult = WSAWaitForMultipleEvents(sizeof(hEventArray) / sizeof(hEventArray[0]),hEventArray,FALSE,WSA_INFINITE,FALSE);
1652
1653                 //\83G\83\89\81[\82Ì\8fê\8d\87
1654                 if(dwResult == WSA_WAIT_FAILED){
1655
1656                         goto err;
1657                 }
1658
1659
1660
1661                 //\83R\83\81\83\93\83g\8eó\90M\83C\83x\83\93\83g\82ª\83V\83O\83i\83\8b\82É\82È\82Á\82½\8fê\8d\87
1662                 if(dwResult - WSA_WAIT_EVENT_0 == 0){
1663
1664                         WSAEnumNetworkEvents(self->chatManager.sock,hRecvEvent,&netEvents);
1665
1666                         //\93Ç\8eæ\83C\83x\83\93\83g\82Ì\8fê\8d\87\83R\83\81\83\93\83g\82ð\8eó\90M\82·\82é
1667                         if(netEvents.lNetworkEvents & FD_READ){
1668
1669
1670                                 recevedLen = recv(self->chatManager.sock,&self->chatManager.recvBuf[messageBufLen],(sizeof(self->chatManager.recvBuf) - 1) - messageBufLen ,0);
1671
1672                                 if(recevedLen == SOCKET_ERROR){
1673                                         self->error = NLIB_ERR_FAILED_NETWORK;
1674
1675                                         goto err;
1676                                 }
1677
1678                                 self->chatManager.recvBuf[messageBufLen + recevedLen] = '\0';
1679
1680
1681
1682
1683
1684
1685                                 NicoLiveParseComment(self,commentBuf,messageBufLen + recevedLen,mailCountBuf,&mailCountBufSize,&commentCountSum,&commentBufSize);
1686
1687
1688
1689
1690
1691                         } else if(netEvents.lNetworkEvents && FD_CLOSE){
1692
1693                                 goto end;
1694
1695                         }//if(netEvents.lNetworkEvents & FD_READ)
1696
1697                 } else if(dwResult - WSA_WAIT_EVENT_0 == 1){
1698
1699                         goto end;
1700
1701                 }//if(dwResult - WSA_WAIT_EVENT_0 == 0)
1702         }
1703
1704
1705 err:
1706
1707         rslt = FALSE;
1708
1709 end:
1710
1711         free(commentBuf);
1712         free(mailCountBuf);
1713         WSACloseEvent(hRecvEvent);
1714
1715         return rslt;
1716 }
1717
1718
1719 static VOID  NicoLiveParseComment(NicoLiveStream_P self,LPWSTR commentBuf,UINT_PTR endSize,LPWSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentCountSum,SIZE_T* commentBufSize){
1720
1721         LPWSTR indexPtr;                                                                                //\89ð\90Í\8e\9e\82Ì\8ew\95W\83|\83C\83\93\83^
1722         NicoLiveChat nicoLiveChat;                                                              //\83`\83\83\83b\83g\83R\83\81\83\93\83g\8ai\94[\97p\8d\\91¢\91Ì
1723         NicoLiveThreadComment nicoLiveThreadComment;                    //\90Ú\91±\89\9e\93\9a\83R\83\81\83\93\83g\8ai\94[\97p\8d\\91¢\91Ì
1724         NicoLiveSendResultComment nicoLiveSendResultComment;    //\91\97\90M\89\9e\93\9a\83R\83\81\83\93\83g\8ai\94[\97p\8d\\91¢\91Ì
1725         NicoLiveChat nicoLiveChatBase;                                                  //\83`\83\83\83b\83g\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì
1726         NicoLiveThreadComment nicoLiveThreadCommentBase;                //\90Ú\91±\89\9e\93\9a\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì
1727         NicoLiveSendResultComment nicoLiveSendResultCommentBase;//\91\97\90M\89\9e\93\9a\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì
1728         LPWSTR attrNameStart;                                                                   //\91®\90«\96¼\8aJ\8en\83|\83C\83\93\83^
1729         LPWSTR attrNameEnd;                                                                             //\91®\90«\96¼\8fI\97¹\83|\83C\83\93\83^
1730         LPWSTR attrValueStart;                                                                  //\91®\90«\92l\8aJ\8en\83|\83C\83\93\83^
1731         LPWSTR attrValueEnd;                                                                    //\91®\90«\92l\8fI\97¹\83|\83C\83\93\83^
1732         INT_PTR nameLen;                                                                                //\91®\90«\82Ì\96¼\91O\82Ì\92·\82³
1733         LPWSTR mailIndexPtr;                                                                    //\83\81\81[\83\8b\91®\90«\92l\89ð\90Í\97p\8ew\95W\83|\83C\83\93\83^
1734         LPWSTR xmlTextPtr;                                                                              //xml\83e\83L\83X\83g\8c`\8e®\82Ì\83f\81[\83^\89ð\90Í\8e\9e\82É\8eg\97p\82·\82é\83|\83C\83\93\83^
1735         LPWSTR xmlTextEnd;                                                                              //xml\83e\83L\83X\83g\8fI\97¹\83|\83C\83\93\83^
1736         LPWSTR* mailIndex;                                                                              //\83\81\81[\83\8b\83R\83}\83\93\83h\83\8a\83X\83g\83|\83C\83\93\83^
1737         BOOL isReceveChat = FALSE;                                                              //\83`\83\83\83b\83g\8eó\90M\83t\83\89\83O
1738         SIZE_T commentSizeCh;                                                                   //\8eó\90M\82µ\82½\83R\83\81\83\93\83g\82ð\83\86\83j\83R\81[\83h\82É\95Ï\8a·\82·\82é\82Æ\82«\82Ì\92·\82³
1739         LPSTR recvBufTmp;                                                                               //\8eó\90M\95\8e\9a\97ñ\91\80\8dì\97p\83|\83C\83\93\83^
1740         LPSTR recvEndPoint;                                                                             //\8eó\90M\95\8e\9a\97ñ\8fI\92[\83|\83C\83\93\83^
1741
1742
1743
1744         recvBufTmp = &self->chatManager.recvBuf[0];
1745         recvEndPoint = &self->chatManager.recvBuf[endSize];
1746
1747
1748         //\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì\8f\89\8aú\89»
1749         nicoLiveChatBase.anonymity = L"";
1750         nicoLiveChatBase.chatBuf = L"";
1751         nicoLiveChatBase.date = L"";
1752         nicoLiveChatBase.locale = L"";
1753         nicoLiveChatBase.mail = mailCountBuf;
1754         nicoLiveChatBase.name = L"";
1755         nicoLiveChatBase.no = L"";
1756         nicoLiveChatBase.premium = L"";
1757         nicoLiveChatBase.thread = L"";
1758         nicoLiveChatBase.user_id = L"";
1759         nicoLiveChatBase.vpos = L"";
1760         nicoLiveChatBase.mailCount = 0;
1761
1762
1763
1764         nicoLiveThreadCommentBase.last_res = L"";
1765         nicoLiveThreadCommentBase.thread = L"";
1766         nicoLiveThreadCommentBase.ticket = L"";
1767
1768
1769         nicoLiveSendResultCommentBase.no = L"";
1770         nicoLiveSendResultCommentBase.status = L"";
1771         nicoLiveSendResultCommentBase.thread = L"";
1772
1773         
1774         //\8eó\90M\82µ\82½\83R\83\81\83\93\83g\82ð\82Ð\82Æ\82Â\82Ìxml\83m\81[\83h\82²\82Æ\82É\89ð\90Í\82·\82é
1775         for (;recvBufTmp + strlen(recvBufTmp) < recvEndPoint;recvBufTmp += strlen(recvBufTmp) + 1){
1776
1777
1778                 commentSizeCh = sizeof(WCHAR) * GetLenToWide(CP_UTF8,recvBufTmp);
1779                 extendMalloc(commentBuf,LPWSTR,*commentBufSize,commentSizeCh);
1780                 MBToWide(CP_UTF8,recvBufTmp,commentBuf,*commentBufSize);
1781
1782                 traceln(TEXT("comment:\r\n%s"),commentBuf);
1783                 //thread\83m\81[\83h\82Ì\8fê\8d\87
1784                 if((indexPtr = wcsstr(commentBuf,L"<thread ")) != NULL){
1785
1786                         indexPtr += wcslen(L"<thread ");
1787                         skipXMLSPACE(indexPtr);
1788
1789
1790
1791
1792                         nicoLiveThreadComment = nicoLiveThreadCommentBase;
1793
1794                         while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1795                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1796
1797
1798                                 nameLen = attrNameEnd - attrNameStart;
1799                                 if(wcsncmp(attrNameStart,L"ticket",nameLen) == 0){
1800
1801
1802                                         partString(nicoLiveThreadComment.ticket,attrValueStart,attrValueEnd);
1803                                         wcscpy(self->ticket,nicoLiveThreadComment.ticket);
1804
1805                                 } else if(wcsncmp(attrNameStart,L"last_res",nameLen) == 0){
1806
1807                                         partString(nicoLiveThreadComment.last_res,attrValueStart,attrValueEnd);
1808
1809
1810                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1811
1812                                         partString(nicoLiveThreadComment.thread,attrValueStart,attrValueEnd);
1813                                 } else if(wcsncmp(attrNameStart,L"server_time",nameLen) == 0){
1814
1815                                         NicoLiveStream_setVpos((*self),attrValueStart);
1816
1817                                         partString(nicoLiveThreadComment.server_time,attrValueStart,attrValueEnd);
1818                                 }
1819
1820                                 skipXMLSPACE(indexPtr);
1821                         }
1822
1823                         
1824
1825                         self->callBack(NICOLIVE_EVENT_RECEVE_CONNECTRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveThreadComment,self->chatManager.commentCount);
1826
1827                         //chat\83m\81[\83h\82Ì\8fê\8d\87
1828                 } else if((indexPtr = wcsstr(commentBuf,L"<chat ")) != NULL){
1829
1830                         indexPtr += wcslen(L"<chat ");
1831                         skipXMLSPACE(indexPtr);
1832
1833
1834
1835                         
1836                         nicoLiveChat = nicoLiveChatBase;
1837
1838                         while(wcsncmp(indexPtr,L">",wcslen(L">"))){
1839
1840                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1841
1842                                 nameLen = attrNameEnd - attrNameStart;
1843
1844
1845                                 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1846
1847                                         partString(nicoLiveChat.no,attrValueStart,attrValueEnd);
1848
1849                                 } else if(wcsncmp(attrNameStart,L"date",nameLen) == 0){
1850
1851                                         NicoLiveStream_setVpos((*self),attrValueStart);
1852
1853                                         partString(nicoLiveChat.date,attrValueStart,attrValueEnd);
1854
1855                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1856
1857                                         partString(nicoLiveChat.thread,attrValueStart,attrValueEnd);
1858
1859                                 } else if(wcsncmp(attrNameStart,L"premium",nameLen) == 0){
1860
1861                                         partString(nicoLiveChat.premium,attrValueStart,attrValueEnd);
1862
1863                                 }  else if(wcsncmp(attrNameStart,L"anonymity",nameLen) == 0){
1864
1865                                         partString(nicoLiveChat.anonymity,attrValueStart,attrValueEnd);
1866
1867
1868                                 } else if(wcsncmp(attrNameStart,L"locale",nameLen) == 0){
1869
1870                                         partString(nicoLiveChat.locale,attrValueStart,attrValueEnd);
1871
1872                                 } else if(wcsncmp(attrNameStart,L"vpos",nameLen) == 0){
1873
1874                                         partString(nicoLiveChat.vpos,attrValueStart,attrValueEnd);
1875
1876                                 } else if(wcsncmp(attrNameStart,L"user_id",nameLen) == 0){
1877
1878                                         partString(nicoLiveChat.user_id,attrValueStart,attrValueEnd);
1879
1880                                 } else if(wcsncmp(attrNameStart,L"name",nameLen) == 0){
1881
1882                                         partString(nicoLiveChat.name,attrNameStart,attrValueEnd);
1883
1884                                 } else if(wcsncmp(attrNameStart,L"mail",nameLen) == 0){
1885
1886                                         nicoLiveChat.mailCount = 1;
1887
1888
1889                                         for(mailIndexPtr = attrValueStart;mailIndexPtr <= attrValueEnd;mailIndexPtr++){
1890
1891                                                 if(mailIndexPtr[0] == L' '){
1892
1893                                                         nicoLiveChat.mailCount++;
1894
1895                                                 }
1896
1897                                         }
1898
1899                                         extendMalloc(mailCountBuf,LPWSTR*,*mailCountBufSize,nicoLiveChat.mailCount);
1900
1901                                         nicoLiveChat.mail = mailCountBuf;
1902                                         mailCountBuf[0] = NULL;
1903
1904                                         for(mailIndex = mailCountBuf,mailIndexPtr = attrValueStart,mailIndex[0] = mailIndexPtr;mailIndexPtr < attrValueEnd;mailIndexPtr++){
1905
1906
1907                                                 if(mailIndexPtr[0] == L' '){
1908                                                         mailIndex++;
1909                                                         mailIndex[0] = mailIndexPtr + 1;
1910                                                         mailIndexPtr[0] = L'\0';
1911
1912
1913                                                 }
1914
1915                                         }
1916
1917                                         mailIndexPtr[0] = L'\0';
1918
1919                                 }
1920
1921                                 skipXMLSPACE(indexPtr);
1922                         }
1923
1924                         indexPtr++;
1925                         xmlTextPtr = indexPtr;
1926                         xmlTextEnd = wcsstr(indexPtr,L"<");
1927                         convertXMLTEXT(nicoLiveChat.chatBuf,indexPtr,xmlTextPtr,xmlTextEnd);
1928
1929
1930
1931
1932                         self->chatManager.commentCount = wcstoul(nicoLiveChat.no,NULL,0);
1933                         (*commentCountSum)++;
1934                         isReceveChat = TRUE;
1935                         self->callBack(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&nicoLiveChat,self->chatManager.commentCount);
1936
1937
1938                         //chat_result\83m\81[\83h\82Ì\8fê\8d\87
1939                 } else if((indexPtr = wcsstr(commentBuf,L"<chat_result ")) != NULL){
1940
1941                         indexPtr += wcslen(L"<chat_result ");
1942
1943                         nicoLiveSendResultComment = nicoLiveSendResultCommentBase;
1944
1945                         while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1946                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1947
1948
1949                                 nameLen = attrNameEnd - attrNameStart;
1950                                 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1951
1952
1953                                         partString(nicoLiveSendResultComment.no,attrValueStart,attrValueEnd);
1954
1955                                 } else if(wcsncmp(attrNameStart,L"status",nameLen) == 0){
1956
1957                                         partString(nicoLiveSendResultComment.status,attrValueStart,attrValueEnd);
1958
1959
1960                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1961
1962                                         partString(nicoLiveSendResultComment.thread,attrValueStart,attrValueEnd);
1963                                 }
1964
1965                                 skipXMLSPACE(indexPtr);
1966                         }
1967
1968                         self->callBack(NICOLIVE_EVENT_RECEVE_CHATSENDRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveSendResultComment,(NICOLIVE_PARAM)NULL);
1969
1970                 }
1971
1972         }
1973
1974         if(recvBufTmp == recvEndPoint && isReceveChat){
1975                 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSETTLE,self,self->option,self->chatManager.commentCount,*commentCountSum);
1976         }
1977
1978
1979
1980
1981         strcpy(&self->chatManager.recvBuf[0],recvBufTmp);
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992         return;
1993
1994 }
1995
1996 static void NicoLiveError(void *buf){
1997
1998         NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1999
2000         nl->callBack(NICOLIVE_EVENT_ERR_CONNECT,nl,nl->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
2001
2002         NicoLiveStream_disConnect(nl);
2003
2004
2005         _endthread();
2006         return;
2007
2008 }
2009
2010 static INLINE SOCKET GetConectedSocket(LPCWSTR nordName,LPCWSTR port,int socktype,int addr_famiry,int protocol){
2011
2012
2013         SOCKET rslt = INVALID_SOCKET;
2014
2015
2016         PADDRINFOW res,res0;
2017         ADDRINFOW hints;
2018         ZeroMemory(&hints,sizeof(hints));
2019         hints.ai_socktype = socktype;
2020         hints.ai_family = addr_famiry;
2021         hints.ai_protocol = protocol;
2022         GetAddrInfoW(nordName,port,&hints,&res0);
2023
2024
2025         for(res = res0; res != NULL;res = res->ai_next){
2026
2027
2028
2029
2030                 rslt = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
2031                 if(rslt == INVALID_SOCKET){
2032
2033                         continue;
2034                 }
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044                 if(connect(rslt,res->ai_addr,(int)res->ai_addrlen) == SOCKET_ERROR){
2045                         closesocket(rslt);
2046                         continue;
2047                 }
2048
2049
2050
2051
2052
2053
2054                 break;
2055
2056         }
2057
2058         if(res == NULL){
2059                 rslt = INVALID_SOCKET;
2060         }
2061
2062
2063         //res\8d\\91¢\91Ì\89ð\95ú
2064         FreeAddrInfo(res0);
2065
2066
2067         return rslt;
2068
2069 }