OSDN Git Service

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