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