OSDN Git Service

クッキー取得ができない現象の調査中
[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         DWORD waitRslt = WSA_WAIT_TIMEOUT;
696
697         do{
698                 while(WSAResetEvent(self->chatManager.startEvent) == FALSE);
699                 while(WSASetEvent(self->chatManager.endEvent)== FALSE);
700
701         
702
703
704
705                 waitRslt = WSAWaitForMultipleEvents(sizeof(self->chatManager.resetEvents) / sizeof(self->chatManager.resetEvents[0]),self->chatManager.resetEvents,TRUE,3000,FALSE);
706         } while(waitRslt == WSA_WAIT_TIMEOUT);
707
708
709         //nicoLiveStream_Initialize(*self);
710         ZeroMemory(&self->playerStatus,sizeof(self->playerStatus));
711         WSAResetEvent(self->chatManager.endEvent);
712         
713         WinHttpCloseHandle(self->sessionManager.getPlayerStatusSession);
714         self->sessionManager.getPlayerStatusSession = NULL;
715         WinHttpCloseHandle(self->sessionManager.heartBeatSession);
716         self->sessionManager.heartBeatSession = NULL;
717
718
719
720         self->isConnecting = FALSE;
721
722
723 end:
724
725
726         return;
727
728
729
730 }
731
732
733 #define NICOLIVE_SENDCHATBUFLEN                 LENGTH_4096
734 #define NICOLIVE_SENDFORMAT                             "<chat thread=\"%d\" ticket=\"%S\"  postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
735
736 NLIB_RESULT NicoLiveStream_sendChat(NicoLiveStream_P self,LPCTSTR chatbuf,LPCTSTR *mail,LPCTSTR *extends){
737
738         NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
739         EnterCriticalSection(&self->sessionManager.cs);
740         
741         {
742                 const UINT_PTR buflen = LENGTH_65536 * 4;
743                 LPVOID chunk = self->sessionManager.buffer;
744
745                 LPSTR postKey;
746                 LPSTR postKeyBuf = (LPSTR)chunk;
747                 LPTSTR postKeyReqBuf = (LPTSTR)&postKeyBuf[NICOLIVE_SENDCHATBUFLEN];
748                 LPTSTR cookieBuf = &postKeyReqBuf[NICOLIVE_SENDCHATBUFLEN];
749                 DWORD statusCode;
750                 DWORD statusCodeSize = sizeof(statusCode);
751                 DWORD readSize;
752
753                 //HINTERNET hWatchLiveNicoVideo = NULL;
754                 HINTERNET hGetPostKeySession = NULL;
755                 
756
757                 if(self->isConnecting == FALSE){
758                         rslt = NLIB_ERR_NOT_LIVECONNECT;
759                         goto errorend;
760                 }
761                 if(chatbuf == NULL || wcslen(chatbuf) >= LENGTH_1024){
762
763                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
764                         goto errorend;
765
766                 }
767
768
769                 //postkey\8eæ\93¾
770                 _swprintf(postKeyReqBuf,L"api/getpostkey?thread=%u&block_no=%u",self->playerStatus.ms.thread,self->chatManager.chatNo / 100);
771
772                 //hWatchLiveNicoVideo = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
773                 hGetPostKeySession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",postKeyReqBuf,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
774
775
776                 //_swprintf(cookieBuf,L"Cookie: %s; %s",self->userSession,self->nicoLiveHistory);
777                 _swprintf(cookieBuf,L"Cookie: %s",self->userSession);
778
779                 if(WinHttpSendRequest(hGetPostKeySession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
780
781                         rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
782                         goto errorend;
783
784                 }
785
786
787                 if(WinHttpReceiveResponse(hGetPostKeySession,NULL) == FALSE){
788
789                         rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
790                         goto errorend;
791
792                 }
793
794
795                 if (WinHttpQueryHeaders(hGetPostKeySession,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
796                         rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
797                         goto errorend;
798                 }
799
800
801                 if (HTTP_STATUS_OK != statusCode){
802                         rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
803                         goto errorend;
804                 }
805
806
807
808
809
810                 if(ReadHttpBody(hGetPostKeySession,(LPBYTE)postKeyBuf,buflen,&readSize) == FALSE){
811
812                         rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
813                         goto errorend;
814
815                 }
816                 postKeyBuf[readSize] = '\0';
817                 postKey = strstr(postKeyBuf,"=") + 1;
818
819
820                 {
821                         LPSTR buffer = (LPSTR)&cookieBuf[NICOLIVE_SENDCHATBUFLEN];
822                         LPSTR indexPtr;
823                         LPSTR mailBuf;
824                         LPSTR extendBuf;
825                 
826                         //mail\83R\83}\83\93\83h\8dì\90¬
827                         if(mail == NULL || mail[0] == NULL){
828
829                                 mailBuf = "";
830
831                         } else {
832                                 INT_PTR len;
833                                 mailBuf = (LPSTR)postKeyReqBuf;
834                                 indexPtr = mailBuf;
835                                 strcpy(indexPtr,"mail=\"");
836                                 indexPtr += strlen(indexPtr);
837
838                                 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
839                                 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
840                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
841                                         goto errorend;
842
843                                 }
844
845                                 
846                                         WideToMB(CP_UTF8,mail[0],indexPtr,len);
847                                         indexPtr += strlen(indexPtr);
848
849
850                                         for(mail++;mail[0] != NULL;mail++){
851
852                                                 indexPtr[0] = ' ';
853                                                 indexPtr++;
854
855                                                 len =  NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
856
857                                                 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
858                                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
859                                                         goto errorend;
860
861                                                 }
862
863                                                 WideToMB(CP_UTF8,mail[0],indexPtr,len);
864                                                 indexPtr += strlen(indexPtr);
865
866                                         }
867                                 
868                                 strcpy(indexPtr,"\"");
869
870
871
872
873                         }
874
875                         //\8ag\92£\91®\90«\8dì\90¬
876                         if(extends == NULL || extends[0] == NULL){
877
878                                 extendBuf = "";
879
880                         } else {
881                                 INT_PTR len;
882                                 extendBuf  =(LPSTR)cookieBuf;
883                                 indexPtr = extendBuf;
884
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 errorend;
891
892                                 }
893                                 WideToMB(CP_UTF8,extends[0],indexPtr,len);
894
895                                 indexPtr += strlen(indexPtr);
896
897                                 strcpy(indexPtr,"=\"");
898                                 indexPtr += strlen(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 errorend;
906
907                                 }
908                                 WideToMB(CP_UTF8,extends[1],indexPtr,len);
909
910
911                                 for(extends+= 2;extends[0] != NULL;extends+=2){
912
913                                         indexPtr[0] = ' ';
914                                         indexPtr++;
915
916                                         len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
917
918                                         if(GetLenToMB(CP_UTF8,extends[0]) >= len){
919                                                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
920                                                 goto errorend;
921
922                                         }
923                                         WideToMB(CP_UTF8,extends[0],indexPtr,len);
924
925                                         indexPtr += strlen(indexPtr);
926
927                                         indexPtr[0] = '=';
928                                         indexPtr++;
929
930
931                                         len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
932
933                                         if(GetLenToMB(CP_UTF8,extends[1]) >= len){
934                                                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
935                                                 goto errorend;
936
937                                         }
938                                         WideToMB(CP_UTF8,extends[1],indexPtr,len);
939
940
941
942                                 }
943                                 indexPtr += strlen(indexPtr);
944                                 strcpy(indexPtr,"\"");
945
946
947
948                         }
949
950                         //\83`\83\83\83b\83g\91\97\90M\83R\83\81\83\93\83g\8dì\90¬
951                         {
952                                 indexPtr = buffer;
953                                 //\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>"
954                                 strcpy(indexPtr,"<chat thread=\"");
955                                 indexPtr += strlen(indexPtr);
956                                 sprintf(indexPtr,"%u",self->playerStatus.ms.thread);
957                                 indexPtr += strlen(indexPtr);
958                                 strcpy(indexPtr,"\" ticket=\"");
959                                 indexPtr += strlen(indexPtr);
960                                 WideToMB(CP_UTF8,self->ticket,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
961                                 indexPtr += strlen(indexPtr);
962                                 strcpy(indexPtr,"\"  postkey=\"");
963                                 indexPtr += strlen(indexPtr);
964                                 strcpy(indexPtr,postKey);
965                                 indexPtr += strlen(indexPtr);
966                                 strcpy(indexPtr,"\" user_id=\"");
967                                 indexPtr += strlen(indexPtr);
968                                 WideToMB(CP_UTF8,self->playerStatus.user.user_id,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
969                                 indexPtr += strlen(indexPtr);
970                                 strcpy(indexPtr,"\" premium=\"");
971                                 indexPtr += strlen(indexPtr);
972                                 sprintf(indexPtr,"%u",self->playerStatus.user.is_premium);
973                                 indexPtr += strlen(indexPtr);
974                                 strcpy(indexPtr,"\" locale=\"");
975                                 indexPtr += strlen(indexPtr);
976                                 WideToMB(CP_UTF8,self->playerStatus.user.userDomain,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
977                                 indexPtr += strlen(indexPtr);
978                                 strcpy(indexPtr,"\" vpos=\"");
979                                 indexPtr += strlen(indexPtr);
980                         
981                         
982                                 timeBeginPeriod(1);
983                                 sprintf(indexPtr,"%u",(self->chatManager.baseVpos + ((timeGetTime() - self->chatManager.commentStartTime) / 10)));
984                                 timeEndPeriod(1);
985                         
986                                 indexPtr += strlen(indexPtr);
987                                 strcpy(indexPtr,"\"");
988                                 indexPtr += strlen(indexPtr);
989
990                                 if(strlen(mailBuf) > 0 && strlen(extendBuf) > 0){
991
992                                         indexPtr[0] = ' ';
993                                         indexPtr++;
994                                         strcpy(indexPtr,mailBuf);
995                                         indexPtr += strlen(indexPtr);
996
997                                         indexPtr[0] = ' ';
998                                         indexPtr++;
999
1000                                         strcpy(indexPtr,extendBuf);
1001                                         indexPtr += strlen(indexPtr);
1002
1003
1004                                 } else if(strlen(mailBuf) > 0){
1005                                         indexPtr[0] = ' ';
1006                                         indexPtr++;
1007                                         strcpy(indexPtr,mailBuf);
1008                                         indexPtr += strlen(indexPtr);
1009
1010                                 } else if(strlen(extendBuf) > 0){
1011                                         indexPtr[0] = ' ';
1012                                         indexPtr++;
1013                                         strcpy(indexPtr,extendBuf);
1014                                         indexPtr += strlen(indexPtr);
1015                                 }
1016                                 strcpy(indexPtr,">");
1017                                 indexPtr += strlen(indexPtr);
1018                                 {
1019                                         LPTSTR sendBuf = (LPTSTR)&buffer[NICOLIVE_SENDCHATBUFLEN * 4];
1020                                         LPTSTR sendPtr = sendBuf;
1021                                         LPCTSTR endPtr= chatbuf + wcslen(chatbuf);
1022
1023
1024                                         //convertTEXT(indexPtr,chatbuf,indexPtr,endPtr);
1025
1026                                         for(;(chatbuf) <= (endPtr);(chatbuf)++){
1027                                                 switch(chatbuf[0]){
1028                                                 case L'&':
1029                                                         wcscpy((sendBuf),L"&amp;");
1030                                                         (sendBuf) += wcslen(sendBuf);
1031                                                         break;
1032                                                 case L'<':
1033                                                         wcscpy((sendBuf),L"&lt;");
1034                                                         (sendBuf) += wcslen(sendBuf);
1035                                                         break;
1036                                                 case L'>':
1037                                                         wcscpy((sendBuf),L"&gt;");
1038                                                         (sendBuf) += wcslen(sendBuf);
1039                                                         break;
1040                                                 case L'\"':
1041                                                         wcscpy((sendBuf),L"&quot;");
1042                                                         (sendBuf) += wcslen(sendBuf);
1043                                                         break;
1044                                                 case L'\'':
1045                                                         wcscpy((sendBuf),L"&apos;");
1046                                                         (sendBuf) += wcslen(sendBuf);
1047                                                         break;
1048                                                 default:
1049                                                         sendBuf[0] = chatbuf[0];
1050                                                         (sendBuf)++;
1051                                                         break;
1052                                                 }
1053                                         }
1054
1055
1056                                         WideToMB(CP_UTF8,sendPtr,indexPtr,NICOLIVE_SENDCHATBUFLEN * 4 - (indexPtr - buffer) - 1);
1057                                         indexPtr += strlen(indexPtr);
1058                                 
1059                                 }
1060                                 strcpy(indexPtr,"</chat>");
1061                                 indexPtr[strlen(indexPtr)] = '\0';
1062
1063
1064
1065                                 {
1066                                         INT_PTR sendLen = 0;
1067                                         INT_PTR sentLen = 0;
1068                                         INT_PTR max = strlen(buffer) + 1;
1069
1070                                         do{
1071                                                 sendLen = send(self->chatManager.sock,buffer,max - sentLen,0);
1072                                                 sentLen += sendLen;
1073                                         } while(sendLen > 0);
1074
1075                                 }
1076                         }
1077                 }
1078
1079                 rslt = NLIB_ERR_OK;
1080                 
1081 errorend:
1082         
1083                 WinHttpCloseHandle(hGetPostKeySession);
1084
1085                 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1086                 LeaveCriticalSection(&self->sessionManager.cs);
1087                 }
1088
1089
1090
1091         return rslt;
1092
1093 }
1094
1095
1096
1097
1098
1099
1100
1101 //
1102 //\83C\83\93\83\89\83C\83\93\8aÖ\90\94
1103 //
1104
1105
1106
1107 NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P self,LPCTSTR userSession,HINTERNET hConnect,LPVOID buffer){
1108
1109         NLIB_RESULT rslt = NLIB_ERR_OK;
1110
1111         
1112         {
1113                 
1114                 const UINT_PTR buflen = LENGTH_65536;
1115                 
1116                 LPSTR recvBuffer = (LPSTR)buffer;
1117                 DWORD readSize;
1118                 DWORD statusCode;
1119                 DWORD statusCodeSize = sizeof(statusCode);
1120
1121
1122         
1123
1124                 if(WinHttpSendRequest(hConnect,userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1125
1126                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1127                         goto end;
1128
1129                 }
1130
1131                 if(WinHttpReceiveResponse(hConnect,NULL) == FALSE){
1132
1133                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1134                         goto end;
1135
1136                 }
1137
1138
1139                 if (WinHttpQueryHeaders(hConnect,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1140                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1141                         goto end;
1142                 }
1143
1144
1145                 if (HTTP_STATUS_OK != statusCode){
1146                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1147                         goto end;
1148                 }
1149
1150
1151
1152
1153                 if(ReadHttpBody(hConnect,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
1154
1155                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1156                         goto end;
1157
1158                 }
1159
1160                 recvBuffer[readSize] = '\0';
1161
1162                 recvBuffer = strstr(recvBuffer,"<");
1163
1164                 if(recvBuffer == NULL){
1165                         
1166                         rslt = NLIB_ERR_GETPLAYERSTATUS_CHANT_PARSE;
1167                         goto end;
1168                 }
1169                 idumpln_mb(CP_UTF8,"playerstatus:%s",recvBuffer);
1170
1171
1172                 XMLParse(self,recvBuffer,NPlayerStatus_ElementStartHandler,NPlayerStatus_ElementEndHandler,NPlayerStatus_CharacterDataHandler);
1173                 rslt = self->error;
1174                 if(rslt != NLIB_ERR_OK){
1175
1176                         goto end;
1177                 }
1178         }
1179
1180 end:
1181
1182         
1183
1184         
1185
1186         return rslt;
1187
1188 }
1189
1190
1191 #define GETNICOLIVEHIS_OBJNAMELENGTH    LENGTH_256
1192 #define GETNICOLIVEHIS_COOKIELENGTH             LENGTH_512
1193
1194 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect){
1195
1196         NLIB_RESULT rslt = NLIB_ERR_OK;
1197
1198         EnterCriticalSection(&self->sessionManager.cs);
1199         {
1200         
1201         HINTERNET hStreamBrowse = NULL;
1202
1203
1204         TCHAR objectName[GETNICOLIVEHIS_OBJNAMELENGTH] = {L"/watch/"};
1205         TCHAR cookie[GETNICOLIVEHIS_COOKIELENGTH] = {L"Cookie: "};
1206         DWORD statusCode;
1207         DWORD statusCodeSize = sizeof(statusCode);
1208         DWORD chunkSize = LENGTH_65536;
1209         LPVOID chunkMemory =self->sessionManager.buffer;
1210         
1211
1212
1213         LPTSTR buffer = (LPTSTR)chunkMemory;
1214
1215
1216
1217         if((GETNICOLIVEHIS_OBJNAMELENGTH - wcslen(objectName) <= wcslen(self->playerStatus.stream.id)) || GETNICOLIVEHIS_COOKIELENGTH - wcslen(cookie) <= wcslen(self->userSession)){
1218
1219                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1220                 goto end;
1221         } 
1222
1223         wcscat(objectName,self->playerStatus.stream.id);
1224         wcscat(cookie,self->userSession);
1225
1226
1227
1228         
1229
1230         hStreamBrowse = WinHttpOpenRequest(hNicoVideoConnect,L"GET",objectName,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1231
1232
1233
1234
1235         if(WinHttpSendRequest(hStreamBrowse,cookie,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1236
1237                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1238                 goto end;
1239
1240         }
1241
1242         if(WinHttpReceiveResponse(hStreamBrowse,NULL) == FALSE){
1243
1244                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1245                 goto end;
1246
1247         }
1248
1249         if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1250                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1251                 goto end;
1252         }
1253
1254
1255         if (HTTP_STATUS_OK != statusCode){
1256                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1257                 goto end;
1258         }
1259
1260
1261
1262         if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_SET_COOKIE,WINHTTP_HEADER_NAME_BY_INDEX,buffer,&chunkSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1263                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1264                 goto end;
1265         }
1266
1267         {
1268                 LPTSTR start =wcsstr(buffer,L"nicolivehistory=");
1269
1270                 LPTSTR end = wcsstr(start,L";");
1271
1272                 UINT_PTR length = end - start;
1273
1274                 if(length >= sizeof(self->nicoLiveHistory)){
1275                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1276                         goto end;
1277
1278                 }
1279
1280                 wcsncpy(self->nicoLiveHistory,start,length);
1281                 self->nicoLiveHistory[length] = L'\0';
1282
1283         }
1284 end:
1285
1286         WinHttpCloseHandle(hStreamBrowse);
1287
1288         }
1289         ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1290         LeaveCriticalSection(&self->sessionManager.cs);
1291
1292
1293         return rslt;
1294
1295
1296
1297 }
1298
1299
1300
1301
1302
1303
1304
1305 #ifdef USE_NLIB_KEEPALIVE
1306 static unsigned int WINAPI  NicoLiveKeapALiveThread(void* lpBuffer){
1307
1308         unsigned int rslt = 0;
1309
1310         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1311
1312         rslt = loopCommon(self,self->chatManager.setKeepAliveTimeEvent,self->chatManager.resetEvents[KEEPALLIVERESETEVENT],self->chatManager.onKeepAlliveSend,&self->chatManager.keepAliveTime);
1313
1314         _endthreadex(rslt);
1315
1316         return rslt;
1317 }
1318 #endif //USE_NLIB_KEEPALIVE
1319
1320 static unsigned int WINAPI  NicoLiveHeartBeatThread(void* lpBuffer){
1321
1322         unsigned int rslt = 0;
1323
1324         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1325
1326
1327         rslt = loopCommon(self,self->chatManager.setHeartBeatTimeEvent,self->chatManager.resetEvents[1],self->chatManager.onHeartBeatSend,&self->chatManager.heartBeatTime);
1328
1329
1330
1331         _endthreadex(rslt);
1332
1333         return rslt;
1334 }
1335 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend,LPDWORD time){
1336
1337         unsigned int rslt = 0;
1338         WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent};   //\83C\83x\83\93\83g\94z\97ñ
1339         WSAEVENT streamEvent[2] = {self->chatManager.endEvent,sendEvent};
1340         DWORD dwResult;                                                                                                                                                                                                 //\83C\83x\83\93\83g\8eó\90M\8c\8b\89Ê
1341         DWORD endResult;
1342
1343         while(TRUE){
1344 restart:
1345                 WSASetEvent(resetEvent);
1346                 
1347                 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1348
1349
1350                 //\83G\83\89\81[\82Ì\8fê\8d\87
1351                 if(dwResult == WSA_WAIT_FAILED){
1352
1353                         goto err;
1354                 }
1355
1356
1357                 switch(dwResult - WSA_WAIT_EVENT_0){
1358
1359                 case 0:
1360
1361                         goto end;
1362
1363                 case 1:
1364                         WSAResetEvent(resetEvent);
1365                         break;
1366
1367                 case 2:
1368                         continue;
1369
1370
1371                 default:
1372
1373                         goto err;
1374
1375                 }
1376
1377                 while(TRUE){
1378                         WSAResetEvent(sendEvent);
1379                         endResult = WSAWaitForMultipleEvents(sizeof(streamEvent) / sizeof(streamEvent[0]),streamEvent,FALSE,*time,FALSE);
1380
1381                         if(endResult == WSA_WAIT_TIMEOUT){
1382
1383                                 nicoLiveOnSend(self);
1384                                 //dumpln(TEXT("onSend"));
1385
1386                                 _heapmin();
1387                         } else{ 
1388                                 switch(endResult - WSA_WAIT_EVENT_0){
1389
1390                                 case 0:
1391                                         goto restart;
1392
1393                                 case 1:
1394                                         break;
1395
1396                                 default:
1397                                         goto err;
1398                                 }
1399                         } 
1400                 }
1401
1402
1403
1404
1405         }
1406
1407 end:
1408         return rslt;
1409
1410 err:
1411         _beginthread(NicoLiveError,0,self);
1412         rslt = 1;
1413         goto end;
1414 }
1415
1416 static VOID OnSendHeartBeat(NicoLiveStream_P self){
1417
1418         if(self->chatManager.heartBeatFlag){
1419                 NicoLiveStream_sendHeartBeat(self);
1420         }
1421
1422 }
1423 #ifdef USE_NLIB_KEEPALIVE
1424 static VOID OnSendKeepAllive(NicoLiveStream_P self){
1425         
1426
1427         if(self->chatManager.keapALiveFlag && self->playerStatus.stream.is_owner == TRUE){
1428                 LPCTSTR mail[2] = {L"184",NULL};
1429                 NicoLiveStream_sendChat(self,L"/keapalive",mail,NULL);
1430         }
1431
1432
1433 }
1434 #endif
1435
1436 #define NICOLIVE_RECEVE_CHAT_LENGTH     LENGTH_2048
1437 #define NICOLIVE_REQUEST_CHAT_LENGTH    LENGTH_256
1438 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer){
1439
1440
1441         unsigned int rslt = 0;
1442
1443         //LPTSTR user_id = NULL;
1444         //LPTSTR name = NULL;
1445         //LPTSTR chatBuf = NULL;
1446
1447
1448
1449         CHAR requestChat[NICOLIVE_REQUEST_CHAT_LENGTH];                                                                                                                                 //\91\97\90M\93d\95\97p\83o\83b\83t\83@
1450         LPCSTR sendFormat = "<thread thread=\"%u\" res_from=\"%d\" version=\"20061206\" />";                                                    //\91\97\90M\93d\95\83t\83H\81[\83}\83b\83g
1451         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;                                                                                                                             //\83j\83R\90\95ú\91\97\83I\83u\83W\83F\83N\83g
1452         INT_PTR sendLen;                                                                                                                                                                                                //\91\97\90M\97p\95\8e\9a\90\94
1453         INT_PTR sentLen;                                                                                                                                                                                                //\91\97\90M\8dÏ\82Ý\95\8e\9a\90\94
1454         WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent};   //\83C\83x\83\93\83g\94z\97ñ
1455         DWORD dwResult;                                                                                                                                                                                                 //\83C\83x\83\93\83g\8eó\90M\8c\8b\89Ê
1456
1457         
1458
1459         while(TRUE){
1460
1461                 WSASetEvent(self->chatManager.resetEvents[0]);
1462
1463                 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1464
1465
1466                 //\83G\83\89\81[\82Ì\8fê\8d\87
1467                 if(dwResult == WSA_WAIT_FAILED){
1468
1469                         goto err;
1470                 }
1471
1472
1473                 switch(dwResult - WSA_WAIT_EVENT_0){
1474
1475                 case 0:
1476
1477                         goto end;
1478
1479                 case 1:
1480                         WSAResetEvent(self->chatManager.resetEvents[0]);
1481                         break;
1482
1483                 case 2:
1484                         continue;
1485
1486                 default:
1487
1488                         goto err;
1489
1490                 }
1491
1492
1493                 sendLen = 0;
1494                 sentLen = 0;
1495
1496                 //\83\\83P\83b\83g\82Ì\90Ý\92è
1497                 self->chatManager.sock = GetConectedSocket(self->playerStatus.ms.addr,self->playerStatus.ms.port,SOCK_STREAM,AF_INET,IPPROTO_TCP);
1498
1499
1500                 //\83R\83\81\83\93\83g\8eó\90M\8aJ\8en\82Ì\89º\8f\80\94õ
1501                 if(self->chatManager.sock == INVALID_SOCKET){
1502                         self->error = NLIB_ERR_FAILED_NETWORK;
1503                         goto err;
1504                 }
1505
1506
1507
1508
1509
1510
1511                 if(NICOLIVE_REQUEST_CHAT_LENGTH <= _scprintf(sendFormat,self->playerStatus.ms.thread,self->res_from)){
1512
1513                         self->error = NLIB_ERR_BUFFER_TOOLITTLE;
1514                         rslt = -1;
1515                         goto err;
1516
1517
1518                 }
1519
1520                 sprintf(requestChat,sendFormat,self->playerStatus.ms.thread,self->res_from);
1521
1522
1523                 //
1524                 //\83R\83\81\83\93\83g\8eó\90M\97v\8b\81\91\97\90M\8f\88\97\9d
1525                 //
1526                 {
1527                         int len;
1528                         sendLen = strlen(requestChat) + 1;
1529                         do{
1530                                 len = send(self->chatManager.sock,requestChat,sendLen,0);
1531                                 if(len == SOCKET_ERROR){
1532                                         self->error = NLIB_ERR_FAILED_NETWORK;
1533                                         rslt = -1;
1534
1535                                         goto err;
1536
1537                                 }
1538
1539                                 sentLen = len;
1540                         }while(sentLen < sendLen);
1541                 }
1542
1543
1544                 if(NicoLiveRecvChatLoop(self) == FALSE){
1545                         goto err;
1546                 }
1547
1548                 
1549         }
1550
1551
1552
1553
1554 err:
1555
1556         _beginthread(NicoLiveError,0,self);
1557
1558 end:
1559
1560
1561
1562         closesocket(self->chatManager.sock);
1563         _endthreadex(rslt);
1564
1565         return rslt;
1566
1567
1568
1569
1570
1571 }
1572
1573
1574
1575
1576
1577 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self){
1578
1579
1580         //
1581         //\83R\83\81\83\93\83g\8eó\90M\8f\88\97\9d
1582         //
1583         BOOL rslt = TRUE;                                                                               //\8c\8b\89Ê
1584         LPTSTR commentBuf = NULL;                                                               //\83R\83\81\83\93\83g\83o\83b\83t\83@
1585         LPTSTR* mailCountBuf = NULL;                                                    //\83\81\81[\83\8b\83|\83C\83\93\83^\83o\83b\83t\83@
1586         INT_PTR recevedLen;                                                                             //\8eó\90M\95\8e\9a\97ñ\92·
1587         INT_PTR messageBufLen;                                                                  //\83o\83b\83t\83@\92·
1588
1589
1590
1591         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ñ
1592         WSANETWORKEVENTS netEvents;                                                             //\83l\83b\83g\83\8f\81[\83N\83C\83x\83\93\83g
1593         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
1594
1595         
1596         SIZE_T commentBufSize = sizeof(TCHAR) * LENGTH_2048;    //\83R\83\81\83\93\83g\83o\83b\83t\83@\92·
1597         SIZE_T mailCountBufSize = sizeof(LPTSTR) * LENGTH_256;  //\83\81\81[\83\8b\82Ì\83|\83C\83\93\83^\97p\83o\83b\83t\83@\92·
1598
1599
1600         WSAEVENT hRecvEvent = NULL;
1601
1602         //\8eó\90M\8f\80\94õ\8f\88\97\9d
1603         self->chatManager.commentCountSum = 0;
1604         hRecvEvent = WSACreateEvent();
1605         self->chatManager.recvBuf[0] = '\0';
1606         WSAEventSelect(self->chatManager.sock, hRecvEvent, FD_READ | FD_CLOSE);
1607         hEventArray[0] = hRecvEvent;
1608         hEventArray[1] = self->chatManager.endEvent;
1609
1610         commentBuf = (LPTSTR)malloc(commentBufSize);
1611         mailCountBuf = (LPTSTR*)malloc(mailCountBufSize);
1612
1613         //\90Ø\92f\82³\82ê\82é\82Ü\82Å\83\8b\81[\83v
1614         while(1){
1615
1616
1617
1618                 //\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é
1619                 messageBufLen = strlen(self->chatManager.recvBuf);
1620
1621                 //\8eó\90M\82©\8fI\97¹\83C\83x\83\93\83g\82ð\8c\9f\92m\82·\82é\82Ü\82Å\91Ò\8b@
1622                 dwResult = WSAWaitForMultipleEvents(sizeof(hEventArray) / sizeof(hEventArray[0]),hEventArray,FALSE,WSA_INFINITE,FALSE);
1623
1624                 //\83G\83\89\81[\82Ì\8fê\8d\87
1625                 if(dwResult == WSA_WAIT_FAILED){
1626
1627                         goto err;
1628                 }
1629
1630
1631
1632                 //\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
1633                 if(dwResult - WSA_WAIT_EVENT_0 == 0){
1634
1635                         WSAEnumNetworkEvents(self->chatManager.sock,hRecvEvent,&netEvents);
1636
1637                         //\93Ç\8eæ\83C\83x\83\93\83g\82Ì\8fê\8d\87\83R\83\81\83\93\83g\82ð\8eó\90M\82·\82é
1638                         if(netEvents.lNetworkEvents & FD_READ){
1639
1640
1641                                 recevedLen = recv(self->chatManager.sock,&self->chatManager.recvBuf[messageBufLen],(sizeof(self->chatManager.recvBuf) - 1) - messageBufLen ,0);
1642
1643                                 if(recevedLen == SOCKET_ERROR){
1644                                         self->error = NLIB_ERR_FAILED_NETWORK;
1645
1646                                         goto err;
1647                                 }
1648
1649                                 self->chatManager.recvBuf[messageBufLen + recevedLen] = '\0';
1650
1651
1652
1653
1654
1655
1656                                 NicoLiveParseComment(self,commentBuf,messageBufLen + recevedLen,mailCountBuf,&mailCountBufSize,&commentBufSize);
1657
1658
1659
1660
1661
1662                         } else if(netEvents.lNetworkEvents && FD_CLOSE){
1663
1664                                 goto end;
1665
1666                         }//if(netEvents.lNetworkEvents & FD_READ)
1667
1668                 } else if(dwResult - WSA_WAIT_EVENT_0 == 1){
1669
1670                         goto end;
1671
1672                 }//if(dwResult - WSA_WAIT_EVENT_0 == 0)
1673         }
1674
1675
1676 err:
1677
1678         rslt = FALSE;
1679
1680 end:
1681         self->callBack(NICOLIVE_EVENT_DISCONNECT,self,self->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
1682         
1683         free(commentBuf);
1684         free(mailCountBuf);
1685         WSACloseEvent(hRecvEvent);
1686
1687         return rslt;
1688 }
1689
1690
1691
1692
1693 static VOID  NicoLiveParseComment(NicoLiveStream_P self,LPTSTR commentBuf,UINT_PTR endSize,LPTSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize){
1694
1695         LPTSTR indexPtr;                                                                                //\89ð\90Í\8e\9e\82Ì\8ew\95W\83|\83C\83\93\83^
1696         NicoLiveChat nicoLiveChat;                                                              //\83`\83\83\83b\83g\83R\83\81\83\93\83g\8ai\94[\97p\8d\\91¢\91Ì
1697         NicoLiveThreadComment nicoLiveThreadComment;                    //\90Ú\91±\89\9e\93\9a\83R\83\81\83\93\83g\8ai\94[\97p\8d\\91¢\91Ì
1698         NicoLiveSendResultComment nicoLiveSendResultComment;    //\91\97\90M\89\9e\93\9a\83R\83\81\83\93\83g\8ai\94[\97p\8d\\91¢\91Ì
1699         NicoLiveChat nicoLiveChatBase;                                                  //\83`\83\83\83b\83g\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì
1700         NicoLiveThreadComment nicoLiveThreadCommentBase;                //\90Ú\91±\89\9e\93\9a\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì
1701         NicoLiveSendResultComment nicoLiveSendResultCommentBase;//\91\97\90M\89\9e\93\9a\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì
1702         LPTSTR attrNameStart;                                                                   //\91®\90«\96¼\8aJ\8en\83|\83C\83\93\83^
1703         LPTSTR attrNameEnd;                                                                             //\91®\90«\96¼\8fI\97¹\83|\83C\83\93\83^
1704         LPTSTR attrValueStart;                                                                  //\91®\90«\92l\8aJ\8en\83|\83C\83\93\83^
1705         LPTSTR attrValueEnd;                                                                    //\91®\90«\92l\8fI\97¹\83|\83C\83\93\83^
1706         INT_PTR nameLen;                                                                                //\91®\90«\82Ì\96¼\91O\82Ì\92·\82³
1707         LPTSTR mailIndexPtr;                                                                    //\83\81\81[\83\8b\91®\90«\92l\89ð\90Í\97p\8ew\95W\83|\83C\83\93\83^
1708         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^
1709         LPTSTR xmlTextEnd;                                                                              //xml\83e\83L\83X\83g\8fI\97¹\83|\83C\83\93\83^
1710         LPTSTR* mailIndex;                                                                              //\83\81\81[\83\8b\83R\83}\83\93\83h\83\8a\83X\83g\83|\83C\83\93\83^
1711         BOOL isReceveChat = FALSE;                                                              //\83`\83\83\83b\83g\8eó\90M\83t\83\89\83O
1712         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³
1713         LPSTR recvBufTmp;                                                                               //\8eó\90M\95\8e\9a\97ñ\91\80\8dì\97p\83|\83C\83\93\83^
1714         LPSTR recvEndPoint;                                                                             //\8eó\90M\95\8e\9a\97ñ\8fI\92[\83|\83C\83\93\83^
1715
1716
1717
1718         recvBufTmp = &self->chatManager.recvBuf[0];
1719         recvEndPoint = &self->chatManager.recvBuf[endSize];
1720
1721
1722         //\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì\8f\89\8aú\89»
1723         nicoLiveChatBase.anonymity = L"";
1724         nicoLiveChatBase.chatBuf = L"";
1725         nicoLiveChatBase.date = L"";
1726         nicoLiveChatBase.locale = L"";
1727         nicoLiveChatBase.mail = mailCountBuf;
1728         nicoLiveChatBase.name = L"";
1729         nicoLiveChatBase.no = L"";
1730         nicoLiveChatBase.premium = L"";
1731         nicoLiveChatBase.thread = L"";
1732         nicoLiveChatBase.user_id = L"";
1733         nicoLiveChatBase.vpos = L"";
1734         nicoLiveChatBase.mailCount = 0;
1735
1736
1737
1738         nicoLiveThreadCommentBase.last_res = L"";
1739         nicoLiveThreadCommentBase.thread = L"";
1740         nicoLiveThreadCommentBase.ticket = L"";
1741
1742
1743         nicoLiveSendResultCommentBase.no = L"";
1744         nicoLiveSendResultCommentBase.status = L"";
1745         nicoLiveSendResultCommentBase.thread = L"";
1746
1747         
1748         //\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é
1749         for (;recvBufTmp + strlen(recvBufTmp) < recvEndPoint;recvBufTmp += strlen(recvBufTmp) + 1){
1750
1751
1752                 commentSizeCh = sizeof(TCHAR) * GetLenToWide(CP_UTF8,recvBufTmp);
1753                 extendMalloc(commentBuf,LPTSTR,*commentBufSize,commentSizeCh);
1754                 MBToWide(CP_UTF8,recvBufTmp,commentBuf,*commentBufSize);
1755
1756                 traceln(TEXT("comment:\r\n%s"),commentBuf);
1757                 //thread\83m\81[\83h\82Ì\8fê\8d\87
1758                 if((indexPtr = wcsstr(commentBuf,L"<thread ")) != NULL){
1759
1760                         indexPtr += wcslen(L"<thread ");
1761                         skipXMLSPACE(indexPtr);
1762
1763
1764
1765
1766                         nicoLiveThreadComment = nicoLiveThreadCommentBase;
1767
1768                         while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1769                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1770
1771
1772                                 nameLen = attrNameEnd - attrNameStart;
1773                                 if(wcsncmp(attrNameStart,L"ticket",nameLen) == 0){
1774
1775
1776                                         partString(nicoLiveThreadComment.ticket,attrValueStart,attrValueEnd);
1777                                         wcscpy(self->ticket,nicoLiveThreadComment.ticket);
1778
1779                                 } else if(wcsncmp(attrNameStart,L"last_res",nameLen) == 0){
1780
1781                                         partString(nicoLiveThreadComment.last_res,attrValueStart,attrValueEnd);
1782
1783
1784                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1785
1786                                         partString(nicoLiveThreadComment.thread,attrValueStart,attrValueEnd);
1787                                 } else if(wcsncmp(attrNameStart,L"server_time",nameLen) == 0){
1788
1789                                         NicoLiveStream_setVpos((*self),attrValueStart);
1790                                         
1791                                         nicoLiveThreadComment.server_time = wcstoul(attrValueStart,NULL,10);
1792                                         //partString(nicoLiveThreadComment.server_time,attrValueStart,attrValueEnd);
1793                                 }
1794
1795                                 skipXMLSPACE(indexPtr);
1796                         }
1797
1798                         
1799
1800                         self->callBack(NICOLIVE_EVENT_RECEVE_CONNECTRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveThreadComment,self->chatManager.chatNo);
1801
1802                         //chat\83m\81[\83h\82Ì\8fê\8d\87
1803                 } else if((indexPtr = wcsstr(commentBuf,L"<chat ")) != NULL){
1804
1805                         indexPtr += wcslen(L"<chat ");
1806                         skipXMLSPACE(indexPtr);
1807
1808
1809
1810                         
1811                         nicoLiveChat = nicoLiveChatBase;
1812
1813                         while(wcsncmp(indexPtr,L">",wcslen(L">"))){
1814
1815                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1816
1817                                 nameLen = attrNameEnd - attrNameStart;
1818
1819
1820                                 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1821
1822                                         partString(nicoLiveChat.no,attrValueStart,attrValueEnd);
1823
1824                                 } else if(wcsncmp(attrNameStart,L"date",nameLen) == 0){
1825
1826                                         NicoLiveStream_setVpos((*self),attrValueStart);
1827
1828                                         partString(nicoLiveChat.date,attrValueStart,attrValueEnd);
1829
1830                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1831
1832                                         partString(nicoLiveChat.thread,attrValueStart,attrValueEnd);
1833
1834                                 } else if(wcsncmp(attrNameStart,L"premium",nameLen) == 0){
1835
1836                                         partString(nicoLiveChat.premium,attrValueStart,attrValueEnd);
1837
1838                                 }  else if(wcsncmp(attrNameStart,L"anonymity",nameLen) == 0){
1839
1840                                         partString(nicoLiveChat.anonymity,attrValueStart,attrValueEnd);
1841
1842
1843                                 } else if(wcsncmp(attrNameStart,L"locale",nameLen) == 0){
1844
1845                                         partString(nicoLiveChat.locale,attrValueStart,attrValueEnd);
1846
1847                                 } else if(wcsncmp(attrNameStart,L"vpos",nameLen) == 0){
1848
1849                                         partString(nicoLiveChat.vpos,attrValueStart,attrValueEnd);
1850
1851                                 } else if(wcsncmp(attrNameStart,L"user_id",nameLen) == 0){
1852
1853                                         partString(nicoLiveChat.user_id,attrValueStart,attrValueEnd);
1854
1855                                 } else if(wcsncmp(attrNameStart,L"name",nameLen) == 0){
1856
1857                                         partString(nicoLiveChat.name,attrNameStart,attrValueEnd);
1858
1859                                 } else if(wcsncmp(attrNameStart,L"mail",nameLen) == 0){
1860
1861                                         nicoLiveChat.mailCount = 1;
1862
1863
1864                                         for(mailIndexPtr = attrValueStart;mailIndexPtr <= attrValueEnd;mailIndexPtr++){
1865
1866                                                 if(mailIndexPtr[0] == L' '){
1867
1868                                                         nicoLiveChat.mailCount++;
1869
1870                                                 }
1871
1872                                         }
1873
1874                                         extendMalloc(mailCountBuf,LPTSTR*,*mailCountBufSize,nicoLiveChat.mailCount);
1875
1876                                         nicoLiveChat.mail = mailCountBuf;
1877                                         mailCountBuf[0] = NULL;
1878
1879                                         for(mailIndex = mailCountBuf,mailIndexPtr = attrValueStart,mailIndex[0] = mailIndexPtr;mailIndexPtr < attrValueEnd;mailIndexPtr++){
1880
1881
1882                                                 if(mailIndexPtr[0] == L' '){
1883                                                         mailIndex++;
1884                                                         mailIndex[0] = mailIndexPtr + 1;
1885                                                         mailIndexPtr[0] = L'\0';
1886
1887
1888                                                 }
1889
1890                                         }
1891
1892                                         mailIndexPtr[0] = L'\0';
1893
1894                                 }
1895
1896                                 skipXMLSPACE(indexPtr);
1897                         }
1898
1899                         indexPtr++;
1900                         xmlTextPtr = indexPtr;
1901                         xmlTextEnd = wcsstr(indexPtr,L"<");
1902                         convertXMLTEXT(nicoLiveChat.chatBuf,indexPtr,xmlTextPtr,xmlTextEnd);
1903
1904
1905
1906                         self->chatManager.chatNo =  wcstoul(nicoLiveChat.no,NULL,10);
1907
1908
1909                         
1910                         self->chatManager.commentCountSum++;
1911                         isReceveChat = TRUE;
1912
1913                         check((_heapchk() == _HEAPOK),TEXT("\83q\81[\83v\83G\83\89\81[\82Å\82·"));
1914
1915                         if((wcscmp(nicoLiveChat.chatBuf,L"/disconnect") == 0 && wcscmp(nicoLiveChat.premium,L"2") == 0)){
1916
1917                                 
1918                                 _beginthread(NicoLiveSelfDisconnect,0,self);
1919                         }
1920                         self->callBack(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&nicoLiveChat,self->chatManager.commentCountSum);
1921                         
1922
1923                         //chat_result\83m\81[\83h\82Ì\8fê\8d\87
1924                 } else if((indexPtr = wcsstr(commentBuf,L"<chat_result ")) != NULL){
1925
1926                         indexPtr += wcslen(L"<chat_result ");
1927
1928                         nicoLiveSendResultComment = nicoLiveSendResultCommentBase;
1929
1930                         while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1931                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1932
1933
1934                                 nameLen = attrNameEnd - attrNameStart;
1935                                 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1936
1937
1938                                         partString(nicoLiveSendResultComment.no,attrValueStart,attrValueEnd);
1939
1940                                 } else if(wcsncmp(attrNameStart,L"status",nameLen) == 0){
1941
1942                                         partString(nicoLiveSendResultComment.status,attrValueStart,attrValueEnd);
1943
1944
1945                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1946
1947                                         partString(nicoLiveSendResultComment.thread,attrValueStart,attrValueEnd);
1948                                 }
1949
1950                                 skipXMLSPACE(indexPtr);
1951                         }
1952
1953 #ifdef USE_NLIB_KEEPALIVE
1954                         //\83L\81[\83v\83A\83\89\83C\83u\83\8a\83Z\83b\83g
1955                         WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
1956 #endif //USE_NLIB_KEEPALIVE
1957
1958                         self->callBack(NICOLIVE_EVENT_RECEVE_CHATSENDRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveSendResultComment,(NICOLIVE_PARAM)NULL);
1959
1960                 }
1961
1962         }
1963
1964         if(recvBufTmp == recvEndPoint && isReceveChat){
1965                 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSETTLE,self,self->option,self->chatManager.chatNo,self->chatManager.commentCountSum);
1966         }
1967
1968
1969
1970
1971         strcpy(&self->chatManager.recvBuf[0],recvBufTmp);
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982         return;
1983
1984 }
1985
1986
1987
1988 static void NicoLiveError(void *buf){
1989
1990         NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1991
1992         nl->callBack(NICOLIVE_EVENT_ERR_CONNECT,nl,nl->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
1993
1994         NicoLiveStream_disConnect(nl);
1995
1996
1997         _endthread();
1998         return;
1999
2000 }
2001
2002 static void NicoLiveSelfDisconnect(void *buf){
2003
2004         NicoLiveStream_P nl = (NicoLiveStream_P)buf;
2005
2006         dumpln(TEXT("selfdisconnect"),);
2007
2008         NicoLiveStream_disConnect(nl);
2009
2010         _heapmin();
2011
2012
2013         _endthread();
2014         return;
2015
2016 }
2017
2018 static INLINE SOCKET GetConectedSocket(LPCTSTR nordName,LPCTSTR port,int socktype,int addr_famiry,int protocol){
2019
2020
2021         SOCKET rslt = INVALID_SOCKET;
2022
2023
2024         PADDRINFOW res,res0;
2025         ADDRINFOW hints;
2026         ZeroMemory(&hints,sizeof(hints));
2027         hints.ai_socktype = socktype;
2028         hints.ai_family = addr_famiry;
2029         hints.ai_protocol = protocol;
2030         GetAddrInfoW(nordName,port,&hints,&res0);
2031
2032
2033         for(res = res0; res != NULL;res = res->ai_next){
2034
2035
2036
2037
2038                 rslt = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
2039                 if(rslt == INVALID_SOCKET){
2040
2041                         continue;
2042                 }
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052                 if(connect(rslt,res->ai_addr,(int)res->ai_addrlen) == SOCKET_ERROR){
2053                         closesocket(rslt);
2054                         continue;
2055                 }
2056
2057
2058
2059
2060
2061
2062                 break;
2063
2064         }
2065
2066         if(res == NULL){
2067                 rslt = INVALID_SOCKET;
2068         }
2069
2070
2071         //res\8d\\91¢\91Ì\89ð\95ú
2072         FreeAddrInfo(res0);
2073
2074
2075         return rslt;
2076
2077 }
2078
2079
2080 //
2081 //\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\8aÖ\98A
2082 //
2083
2084 ///
2085 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82ÌID\82ð\8eæ\93¾
2086 ///
2087 NLIB_DECLSPEC LPCTSTR NicoLiveStream_getId(NicoLiveStream_P self){
2088
2089         return self->playerStatus.stream.id;
2090 }
2091
2092
2093 ///
2094 ///\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¾
2095 ///
2096 NLIB_DECLSPEC LPCTSTR NicoLiveStream_getDefaultCommunity(NicoLiveStream_P self){
2097
2098         return self->playerStatus.stream.default_community;
2099 }
2100
2101
2102 ///
2103 ///\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¾
2104 ///
2105 PROVIDERTYPE NicoLiveStream_getProviderType(NicoLiveStream_P self){
2106
2107         return self->playerStatus.stream.provider_type;
2108 }
2109
2110
2111 ///
2112 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82Ì\83I\81[\83i\81[\83t\83\89\83O\82ð\8eæ\93¾
2113 ///
2114 BOOL NicoLiveStream_isOwner(NicoLiveStream_P self){
2115
2116         return self->playerStatus.stream.is_owner;
2117 }
2118
2119 ///
2120 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82Ì\8aJ\8en\8e\9e\8d\8f\82ð\8eæ\93¾
2121 ///
2122 time_t NicoLiveStream_getStartTime(NicoLiveStream_P self){
2123
2124         return self->playerStatus.stream.start_time;
2125 }
2126
2127 ///
2128 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82Ì\8fI\97¹\8e\9e\8d\8f\82ð\8eæ\93¾
2129 ///
2130 time_t NicoLiveStream_getEndTime(NicoLiveStream_P self){
2131
2132         return self->playerStatus.stream.end_time;
2133 }
2134
2135 ///
2136 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82Ì\8aJ\8fê\8e\9e\8d\8f\82ð\8eæ\93¾
2137 ///
2138 time_t NicoLiveStream_getOpenTime(NicoLiveStream_P self){
2139
2140         return self->playerStatus.stream.open_time;
2141
2142 }
2143
2144 ///
2145 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82Ì\83x\81[\83X\8e\9e\8d\8f\82ð\8eæ\93¾
2146 ///
2147 time_t NicoLiveStream_getBaseTime(NicoLiveStream_P self){
2148
2149         return self->playerStatus.stream.base_time;
2150 }
2151
2152
2153 ///
2154 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82Ì\83^\83C\83g\83\8b\8eæ\93¾
2155 ///
2156 LPCTSTR NicoLiveStream_getTitle(NicoLiveStream_P self){
2157 #ifdef PLAYERSTATUS_GET_TITLE
2158         return self->playerStatus.stream.title;
2159 #else
2160         static const LPCTSTR rslt = TEXT("");
2161         return rslt;
2162 #endif
2163 }
2164
2165 BOOL NicoLiveStream_isPremium(NicoLiveStream_P self){
2166
2167         return self->playerStatus.user.is_premium;
2168
2169 }