2 #include "nlib_include.h"
9 static NicoLiveHeartBeatContainer heartBeatContainer;
10 static CRITICAL_SECTION heartBeatCs;
17 #define XMLSPACE L" \t\r\n"
19 #define parseAttr(indexPtr,ans,ane,avs,ave)\
21 (ane) = wcspbrk((ans),XMLSPACE L"=");\
22 (avs) = wcsstr((ane),L"\"") + 1;\
23 (ave) = wcsstr((avs),L"\"");\
24 (indexPtr) = (ave) + 1
26 #define skipXMLSPACE(indexPtr)\
27 for(;(*(indexPtr)) == L' ' || (*(indexPtr)) == '\t' || (*(indexPtr)) == '\r' || (*(indexPtr)) == '\n';indexPtr++)
29 #define partString(ptr,start,end)\
34 #define convertXMLTEXT(buf,basePtr,convPtr,endPtr)\
36 for(;(basePtr) < (endPtr);(basePtr)++,(convPtr)++){\
37 if(wcsncmp((basePtr),L"&",wcslen(L"&")) == 0){\
39 (basePtr) += wcslen(L"&") - 1;\
40 } else if(wcsncmp((basePtr),L"<",wcslen(L"<")) == 0){\
42 (basePtr) += wcslen(L"<") - 1;\
43 } else if(wcsncmp((basePtr),L">",wcslen(L">")) == 0){\
45 (basePtr) += wcslen(L">") - 1;\
46 } else if(wcsncmp((basePtr),L""",wcslen(L""")) == 0){\
47 (convPtr)[0] = L'\"';\
48 (basePtr) += wcslen(L""") - 1;\
49 } else if(wcsncmp((basePtr),L"'",wcslen(L"'")) == 0){\
50 (convPtr)[0] = L'\'';\
51 (basePtr) += wcslen(L"'") - 1;\
53 (convPtr)[0] = (basePtr)[0];\
58 #define getBaseVpos(server_time,base_time) (((server_time) - (base_time)) * 100)
60 #define setMsec(mSec)\
62 (mSec) = timeGetTime();\
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)
73 //
\83v
\83\89\83C
\83x
\81[
\83g
\8aÖ
\90\94
77 ///
\83v
\83\8c\83C
\83\84\81[
\83X
\83e
\81[
\83^
\83X
\8eæ
\93¾
79 static INLINE NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P pPlayerStatus,LPCWSTR userSession,HINTERNET hConnect,LPVOID buffer);
82 ///nicoLiveHistory
\8eæ
\93¾
84 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect);
98 ///
\83`
\83\83\83b
\83g
\8eó
\90M
\83\8b\81[
\83v
\8aJ
\8en
\8aÖ
\90\94
100 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer);
103 ///
\83n
\81[
\83g
\83r
\81[
\83g
\91\97\90M
\83\8b\81[
\83v
\8aÖ
\90\94
105 static unsigned int WINAPI NicoLiveHeartBeatThread(void* lpBuffer);
109 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\91\97\90M
\83\8b\81[
\83v
\8aÖ
\90\94
111 static unsigned int WINAPI NicoLiveKeapALiveThread(void* lpBuffer);
117 ///
\83`
\83\83\83b
\83g
\8eó
\90M
\83\8b\81[
\83v
\8aÖ
\90\94
119 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self);
124 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend);
127 ///
\83R
\83\81\83\93\83g
\89ð
\90Í
\8aÖ
\90\94
129 static VOID NicoLiveParseComment(NicoLiveStream_P self,LPWSTR commentBuf,UINT_PTR endSize,LPWSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize);
131 static void NicoLiveError(void *buf);
133 static void NicoLiveSelfDisconnect(void *buf);
135 static VOID OnSendHeartBeat(NicoLiveStream_P self);
137 static VOID OnSendKeepAllive(NicoLiveStream_P self);
139 ///
\83\
\83P
\83b
\83g
\8eæ
\93¾
\8aÖ
\90\94
141 static INLINE SOCKET GetConectedSocket(LPCWSTR nordName,LPCWSTR port,int socktype,int addr_famiry,int protocol);
144 StreamStatus_P NicoLiveStream_getStreamStatus(NicoLiveStream_P self){
146 return &self->playerStatus.stream;
149 BOOL Initialize_NicoLive(){
155 //
\83n
\81[
\83g
\83r
\81[
\83g
\83R
\83\93\83e
\83i
\8f\89\8aú
\89»
156 ZeroMemory(&heartBeatContainer,sizeof(heartBeatContainer));
157 heartBeatContainer.is_restrictSize = sizeof(WCHAR) * LENGTH_1024;
158 heartBeatContainer.is_restrictBuff = (LPWSTR)calloc(1,heartBeatContainer.is_restrictSize);
159 heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
161 heartBeatContainer.ticketSize = sizeof(WCHAR) * LENGTH_1024;
162 heartBeatContainer.ticketBuff = (LPWSTR)calloc(1,heartBeatContainer.ticketSize);
163 heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
165 InitializeCriticalSection(&heartBeatCs);
175 extern BOOL Finalize_NicoLive(){
178 DeleteCriticalSection(&heartBeatCs);
180 //
\83p
\81[
\83T
\8cã
\8f\88\97\9d
181 free(heartBeatContainer.is_restrictBuff);
182 free(heartBeatContainer.ticketBuff);
196 NicoLiveStream_P NicoLiveStream_new(){
197 //
\90¶
\90¬&
\8f\89\8aú
\89»
198 NicoLiveStream_P self = (NicoLiveStream_P)calloc(1,sizeof(NicoLiveStream));
200 //
\8f\89\8aú
\92l
\82Ì
\90Ý
\92è
201 self->chatManager.onHeartBeatSend = OnSendHeartBeat;
203 self->chatManager.onKeepAlliveSend = OnSendKeepAllive;
205 InitializeCriticalSection(&self->sessionManager.cs);
207 self->chatManager.heartBeatTime = 300000;
209 self->chatManager.heartBeatFlag = TRUE;
211 self->chatManager.keepAliveTime = 300000;
213 self->chatManager.keapALiveFlag = TRUE;
215 self->isConnecting = FALSE;
217 self->chatManager.endEvent = WSACreateEvent();
219 self->chatManager.startEvent = WSACreateEvent();
221 self->chatManager.deleteEvent = WSACreateEvent();
223 self->chatManager.setHeartBeatTimeEvent = WSACreateEvent();
225 self->chatManager.setKeepAliveTimeEvent = WSACreateEvent();
227 self->chatManager.resetEvents[0] = WSACreateEvent();
229 self->chatManager.resetEvents[1] = WSACreateEvent();
231 self->chatManager.resetEvents[2] = WSACreateEvent();
237 //
\83X
\83\8c\83b
\83h
\82Ì
\8aJ
\8en
238 self->chatManager.hRecvChatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveRecvChat,self,0,&self->chatManager.recvChatThreadID);
240 self->chatManager.hHeartBeatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveHeartBeatThread,self,0,&self->chatManager.heartBeatThreadID);
242 self->chatManager.hKeapALiveHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveKeapALiveThread,self,0,&self->chatManager.keapALiveThreadID);
250 dumpln(TEXT("size%d"),sizeof(NicoLiveStream));
260 //
\83j
\83R
\83j
\83R
\90¶
\95ú
\91\97\8aÖ
\98A
\8aÖ
\90\94
261 ///////////////////////////////////////////////////
263 VOID NicoLiveStream_delete(NicoLiveStream_P* self){
265 NicoLiveStream_disConnect((*self));
267 WSASetEvent((*self)->chatManager.deleteEvent);
269 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hRecvChatHandle){
270 WaitForSingleObject( (*self)->chatManager.hRecvChatHandle, INFINITE );
271 CloseHandle((*self)->chatManager.hRecvChatHandle);
274 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hHeartBeatHandle){
276 WaitForSingleObject((*self)->chatManager.hHeartBeatHandle,INFINITE);
277 CloseHandle((*self)->chatManager.hHeartBeatHandle);
280 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hKeapALiveHandle){
282 WaitForSingleObject((*self)->chatManager.hKeapALiveHandle,INFINITE);
283 CloseHandle((*self)->chatManager.hKeapALiveHandle);
293 //
\8cã
\8f\88\97\9d&
\94j
\8aü
295 DeleteCriticalSection(&(*self)->sessionManager.cs);
297 WSACloseEvent((*self)->chatManager.setHeartBeatTimeEvent);
299 WSACloseEvent((*self)->chatManager.setKeepAliveTimeEvent);
301 WSACloseEvent((*self)->chatManager.endEvent);
303 WSACloseEvent((*self)->chatManager.startEvent);
305 WSACloseEvent((*self)->chatManager.deleteEvent);
307 WSACloseEvent((*self)->chatManager.resetEvents[0]);
309 WSACloseEvent((*self)->chatManager.resetEvents[1]);
311 WSACloseEvent((*self)->chatManager.resetEvents[2]);
318 (*self) = (NicoLiveStream_P)NULL;
325 ///
\83n
\81[
\83g
\83r
\81[
\83g
\82Ì
\8aÔ
\8au
\82ð
\90Ý
\92è
\81i
\83~
\83\8a\95b)
327 VOID NicoLiveStream_setHeartBeatMsec(NicoLiveStream_P self,DWORD msec){
329 WSASetEvent(self->chatManager.setHeartBeatTimeEvent);
330 self->chatManager.heartBeatTime = msec;
335 ///
\83n
\81[
\83g
\83r
\81[
\83g
\82Ì
\8aÔ
\8au
\82ð
\8eæ
\93¾(
\83~
\83\8a\95b)
337 DWORD NicoLiveStream_getHeartBeatMsec(NicoLiveStream_P self){
339 return self->chatManager.heartBeatTime;
345 ///
\83n
\81[
\83g
\83r
\81[
\83g
\97L
\8cø
\81E
\96³
\8cø
\90Ý
\92è
347 VOID NicoLiveStream_setHeartBeatFlag(NicoLiveStream_P self,BOOL flag){
349 self->chatManager.heartBeatFlag = flag;
355 ///
\83n
\81[
\83g
\83r
\81[
\83g
\97L
\8cø
\83t
\83\89\83O
\8eæ
\93¾
357 BOOL NicoLiveStream_getHeartBeatFlag(NicoLiveStream_P self){
359 return self->chatManager.heartBeatFlag;
366 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\82Ì
\8aÔ
\8au
\82ð
\90Ý
\92è(
\83~
\83\8a\95b)
368 VOID NicoLiveStream_setKeapALiveMsec(NicoLiveStream_P self,DWORD msec){
370 WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
371 self->chatManager.keepAliveTime = msec;
378 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\82Ì
\8aÔ
\8au
\82ð
\8eæ
\93¾(
\83~
\83\8a\95b)
380 DWORD NicoLiveStream_getKeapALiveMsec(NicoLiveStream_P self){
382 return self->chatManager.keepAliveTime;
388 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\97L
\8cø
\81E
\96³
\8cø
\90Ý
\92è
390 VOID NicoLiveStream_setKeapALiveFlag(NicoLiveStream_P self,BOOL flag){
392 self->chatManager.keapALiveFlag = flag;
397 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\83t
\83\89\83O
\8eæ
\93¾
399 BOOL NicoLiveStream_getKeapALiveFlag(NicoLiveStream_P self){
401 return self->chatManager.keapALiveFlag;
405 VOID NicoLiveStrream_setResFrom(NicoLiveStream_P self,INT_PTR res){
409 self->res_from = (res < 0 || res > 1000) ? 0 : ((-1) * res);
413 INT_PTR NicoLiveStream_getResFrom(NicoLiveStream_P self){
415 return (-1) * self->res_from;
418 NLIB_RESULT NicoLiveStream_connect(NicoLiveStream_P self,NicoVideoAuth_P nicoVideoAuth,LPCWSTR url,NicoRecvCallBack callback,LPVOID option){
420 #define NICOLIVE_CONNECTIONSTREAM_COOKIE_COUNT 1
421 #define LIVENO_LENGTH LENGTH_NICOLIVEID
423 NLIB_RESULT rslt = NLIB_ERR_OK;
431 //url
\82©
\82ç
\90Ú
\91±
\94Ô
\8d\86\82ð
\92\8a\8fo
432 LPCWSTR pInputLiveNo = url;
433 LPCWSTR psrech = wcsstr(url,L"http://");
434 LPCWSTR pInputLiveNoEnd;
435 WCHAR liveNo[LIVENO_LENGTH] = {0};
438 if(self == NULL)goto end;
440 //
\91O
\82É
\82Â
\82È
\82¢
\82Å
\82¢
\82½
\95ú
\91\97\82ð
\90Ø
\92f
441 NicoLiveStream_disConnect(self);
447 for(;psrech != NULL;psrech = wcsstr(psrech +1,L"/")){
449 pInputLiveNo = psrech + 1;
455 pInputLiveNoEnd = wcsstr(pInputLiveNo,L"?");
457 if(pInputLiveNoEnd == NULL){
459 pInputLiveNoEnd = pInputLiveNo + wcslen(pInputLiveNo);
463 if(pInputLiveNo == NULL){
465 rslt = NLIB_LIVENO_FAILED_INPUT;
468 }else if(pInputLiveNoEnd - pInputLiveNo + 2 >= LIVENO_LENGTH - 1){
470 rslt = NLIB_LIVENO_FAILED_TOOBIG;
473 } else if((wcsncmp(pInputLiveNo,TEXT("lv"),2) == 0)||(( wcsncmp(pInputLiveNo,TEXT("co"),2) == 0) || (wcsncmp(pInputLiveNo,TEXT("ch"),2) == 0) )){
476 wcsncpy(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
479 } else if(_wtoi(pInputLiveNo) != 0){
481 wcscpy(liveNo,L"lv");
482 wcsncat(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
486 rslt = NLIB_LIVENO_FAILED_UNDEFEINE;
495 wcsncpy(self->userSession,L"Cookie: ",sizeof(self->userSession) / sizeof(self->userSession[0]) - 1);
496 wcsncat(self->userSession,nicoVideoAuth->userSession,sizeof(self->userSession) / sizeof(self->userSession[0]) - 1);
497 self->userSession[sizeof(self->userSession) / sizeof(self->userSession[0]) - 1] = L'\0';
503 WCHAR objectName[LENGTH_256] = {L"api/getplayerstatus?v="};
504 wcsncat(objectName,liveNo,sizeof(objectName) / sizeof(objectName[0]));
510 self->sessionManager.getPlayerStatusSession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
513 //
\83v
\83\8c\83C
\83\84\81[
\83X
\83e
\81[
\83^
\83X
\8eæ
\93¾
514 EnterCriticalSection(&self->sessionManager.cs);
515 rslt = GetPlayerStatus(&self->playerStatus,self->userSession,self->sessionManager.getPlayerStatusSession,self->sessionManager.buffer);
516 LeaveCriticalSection(&self->sessionManager.cs);
518 if(rslt != NLIB_ERR_OK){
525 //
\90¶
\95ú
\91\97\83I
\83u
\83W
\83F
\83N
\83g
\82É
\8ae
\88ø
\90\94\82ð
\90Ý
\92è
527 self->callBack = callback;
528 self->option = option;
531 WSASetEvent(self->chatManager.startEvent);
533 self->isConnecting = TRUE;
535 //nicoLiveHistory
\82ð
\8eæ
\93¾(
\95K
\97v
\82È
\82µ
\81H)
536 //GetNicoLiveHistory(self,hWatchLiveNicVideo);
545 NLIB_RESULT NicoLiveStream_sendHeartBeat(NicoLiveStream_P self){
548 NLIB_RESULT rslt = NLIB_ERR_OK;
550 if(self->isConnecting == FALSE){
551 rslt = NLIB_ERR_NOT_CONNECT;
554 if(self == NULL || self->playerStatus.error != NLIB_ERR_OK){
556 rslt = NLIB_ERR_PLAYERSTATUS_ERROR;
562 EnterCriticalSection(&self->sessionManager.cs);
564 //HINTERNET hWatchLiveNicoSession = NULL;
565 //HINTERNET hGetPlayerStatusRequest = NULL;
566 const UINT_PTR buflen = LENGTH_65536;
567 LPVOID buffer = self->sessionManager.buffer;
569 LPWSTR objectName = (LPWSTR)buffer;
571 //LPWSTR sendBuffer = (LPWSTR)&objectName[LENGTH_4096];
572 LPSTR recvBuffer = (LPSTR)&objectName[LENGTH_4096];
575 DWORD statusCodeSize = sizeof(statusCode);
577 //hWatchLiveNicoSession = hWatchLiveNicoConnect;
579 wcscpy(objectName,L"/api/heartbeat?v=");
580 indexPtr = objectName + wcslen(objectName);
581 wcscpy(indexPtr,self->playerStatus.stream.id);
582 //wcscpy(sendBuffer,L"Cookie: ");
583 //indexPtr = sendBuffer + wcslen(sendBuffer);
584 wcscpy(indexPtr,self->userSession);
589 if(self->sessionManager.heartBeatSession == NULL){
590 self->sessionManager.heartBeatSession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
593 if(WinHttpSendRequest(self->sessionManager.heartBeatSession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
595 rslt = NLIB_ERR_FAILED_NETWORK;
600 if(WinHttpReceiveResponse(self->sessionManager.heartBeatSession,NULL) == FALSE){
602 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
608 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){
609 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
614 if (HTTP_STATUS_OK != statusCode){
615 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
620 //recvBuffer = (LPSTR)sendBuffer;
623 if(ReadHttpBody(self->sessionManager.heartBeatSession,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
625 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
633 EnterCriticalSection(&heartBeatCs);
635 XMLParse(&heartBeatContainer,recvBuffer,NicoLiveHeartBeat_ElementStartHandler,NicoLiveHeartBeat_ElementEndHandler,NicoLiveHeartBeat_CharacterDataHandler);
637 self->chatManager.baseVpos = getBaseVpos(heartBeatContainer.heartBeat.time, self->playerStatus.stream.base_time);
638 setMsec(self->chatManager.commentStartTime);
640 self->callBack(NICOLIVE_EVENT_SEND_HEARTBEAT,self,self->option,(NICOLIVE_PARAM)&heartBeatContainer.heartBeat,(NICOLIVE_PARAM)NULL);
642 ZeroMemory(&heartBeatContainer.heartBeat,sizeof(heartBeatContainer.heartBeat));
644 ZeroMemory(heartBeatContainer.is_restrictBuff,heartBeatContainer.is_restrictSize);
646 ZeroMemory(heartBeatContainer.ticketBuff,heartBeatContainer.ticketSize);
648 heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
650 heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
652 LeaveCriticalSection(&heartBeatCs);
657 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
658 LeaveCriticalSection(&self->sessionManager.cs);
670 VOID NicoLiveStream_disConnect(NicoLiveStream_P self){
672 if(self == NULL)goto end;
674 while(WSAResetEvent(self->chatManager.startEvent) == FALSE);
675 while(WSASetEvent(self->chatManager.endEvent)== FALSE);
681 WSAWaitForMultipleEvents(sizeof(self->chatManager.resetEvents) / sizeof(self->chatManager.resetEvents[0]),self->chatManager.resetEvents,TRUE,WSA_INFINITE,FALSE);
685 //nicoLiveStream_Initialize(*self);
686 ZeroMemory(&self->playerStatus,sizeof(self->playerStatus));
687 WSAResetEvent(self->chatManager.endEvent);
689 WinHttpCloseHandle(self->sessionManager.getPlayerStatusSession);
690 self->sessionManager.getPlayerStatusSession = NULL;
691 WinHttpCloseHandle(self->sessionManager.heartBeatSession);
692 self->sessionManager.heartBeatSession = NULL;
696 self->isConnecting = FALSE;
708 #define NICOLIVE_SENDCHATBUFLEN LENGTH_4096
709 #define NICOLIVE_SENDFORMAT "<chat thread=\"%d\" ticket=\"%S\" postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
711 NLIB_RESULT NicoLiveStream_sendChat(NicoLiveStream_P self,LPCWSTR chatbuf,LPCWSTR *mail,LPCWSTR *extends){
713 NLIB_RESULT rslt = NLIB_ERR_OK;
714 EnterCriticalSection(&self->sessionManager.cs);
717 const UINT_PTR buflen = LENGTH_65536 * 4;
718 LPVOID chunk = self->sessionManager.buffer;
721 LPSTR postKeyBuf = (LPSTR)chunk;
722 LPWSTR postKeyReqBuf = (LPWSTR)&postKeyBuf[NICOLIVE_SENDCHATBUFLEN];
723 LPWSTR cookieBuf = &postKeyReqBuf[NICOLIVE_SENDCHATBUFLEN];
725 DWORD statusCodeSize = sizeof(statusCode);
728 //HINTERNET hWatchLiveNicoVideo = NULL;
729 HINTERNET hGetPostKeySession = NULL;
732 if(self->isConnecting == FALSE){
733 rslt = NLIB_ERR_NOT_CONNECT;
736 if(chatbuf == NULL || wcslen(chatbuf) >= LENGTH_1024){
738 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
745 _swprintf(postKeyReqBuf,L"api/getpostkey?thread=%u&block_no=%u",self->playerStatus.ms.thread,self->chatManager.chatNo / 100);
747 //hWatchLiveNicoVideo = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
748 hGetPostKeySession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",postKeyReqBuf,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
751 //_swprintf(cookieBuf,L"Cookie: %s; %s",self->userSession,self->nicoLiveHistory);
752 _swprintf(cookieBuf,L"Cookie: %s",self->userSession);
754 if(WinHttpSendRequest(hGetPostKeySession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
756 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
762 if(WinHttpReceiveResponse(hGetPostKeySession,NULL) == FALSE){
764 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
770 if (WinHttpQueryHeaders(hGetPostKeySession,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
771 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
776 if (HTTP_STATUS_OK != statusCode){
777 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
785 if(ReadHttpBody(hGetPostKeySession,(LPBYTE)postKeyBuf,buflen,&readSize) == FALSE){
787 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
791 postKeyBuf[readSize] = '\0';
792 postKey = strstr(postKeyBuf,"=") + 1;
796 LPSTR buffer = (LPSTR)&cookieBuf[NICOLIVE_SENDCHATBUFLEN];
801 //mail
\83R
\83}
\83\93\83h
\8dì
\90¬
808 mailBuf = (LPSTR)postKeyReqBuf;
810 strcpy(indexPtr,"mail=\"");
811 indexPtr += strlen(indexPtr);
813 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
814 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
815 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
820 WideToMB(CP_UTF8,mail[0],indexPtr,len);
821 indexPtr += strlen(indexPtr);
824 for(mail++;mail[0] != NULL;mail++){
829 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
831 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
832 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
837 WideToMB(CP_UTF8,mail[0],indexPtr,len);
838 indexPtr += strlen(indexPtr);
841 strcpy(indexPtr,"\"");
848 //
\8ag
\92£
\91®
\90«
\8dì
\90¬
855 extendBuf =(LPSTR)cookieBuf;
856 indexPtr = extendBuf;
859 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
861 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
862 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
866 WideToMB(CP_UTF8,extends[0],indexPtr,len);
868 indexPtr += strlen(indexPtr);
870 strcpy(indexPtr,"=\"");
871 indexPtr += strlen(indexPtr);
874 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
876 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
877 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
881 WideToMB(CP_UTF8,extends[1],indexPtr,len);
884 for(extends+= 2;extends[0] != NULL;extends+=2){
889 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
891 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
892 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
896 WideToMB(CP_UTF8,extends[0],indexPtr,len);
898 indexPtr += strlen(indexPtr);
904 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
906 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
907 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
911 WideToMB(CP_UTF8,extends[1],indexPtr,len);
916 indexPtr += strlen(indexPtr);
917 strcpy(indexPtr,"\"");
923 //
\83`
\83\83\83b
\83g
\91\97\90M
\83R
\83\81\83\93\83g
\8dì
\90¬
926 //
\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>"
927 strcpy(indexPtr,"<chat thread=\"");
928 indexPtr += strlen(indexPtr);
929 sprintf(indexPtr,"%u",self->playerStatus.ms.thread);
930 indexPtr += strlen(indexPtr);
931 strcpy(indexPtr,"\" ticket=\"");
932 indexPtr += strlen(indexPtr);
933 WideToMB(CP_UTF8,self->ticket,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
934 indexPtr += strlen(indexPtr);
935 strcpy(indexPtr,"\" postkey=\"");
936 indexPtr += strlen(indexPtr);
937 strcpy(indexPtr,postKey);
938 indexPtr += strlen(indexPtr);
939 strcpy(indexPtr,"\" user_id=\"");
940 indexPtr += strlen(indexPtr);
941 WideToMB(CP_UTF8,self->playerStatus.user.user_id,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
942 indexPtr += strlen(indexPtr);
943 strcpy(indexPtr,"\" premium=\"");
944 indexPtr += strlen(indexPtr);
945 sprintf(indexPtr,"%u",self->playerStatus.user.is_premium);
946 indexPtr += strlen(indexPtr);
947 strcpy(indexPtr,"\" locale=\"");
948 indexPtr += strlen(indexPtr);
949 WideToMB(CP_UTF8,self->playerStatus.user.userDomain,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
950 indexPtr += strlen(indexPtr);
951 strcpy(indexPtr,"\" vpos=\"");
952 indexPtr += strlen(indexPtr);
956 sprintf(indexPtr,"%u",(self->chatManager.baseVpos + ((timeGetTime() - self->chatManager.commentStartTime) / 10)));
959 indexPtr += strlen(indexPtr);
960 strcpy(indexPtr,"\"");
961 indexPtr += strlen(indexPtr);
963 if(strlen(mailBuf) > 0 && strlen(extendBuf) > 0){
967 strcpy(indexPtr,mailBuf);
968 indexPtr += strlen(indexPtr);
973 strcpy(indexPtr,extendBuf);
974 indexPtr += strlen(indexPtr);
977 } else if(strlen(mailBuf) > 0){
980 strcpy(indexPtr,mailBuf);
981 indexPtr += strlen(indexPtr);
983 } else if(strlen(extendBuf) > 0){
986 strcpy(indexPtr,extendBuf);
987 indexPtr += strlen(indexPtr);
989 strcpy(indexPtr,">");
990 indexPtr += strlen(indexPtr);
992 LPWSTR sendBuf = (LPWSTR)&buffer[NICOLIVE_SENDCHATBUFLEN * 4];
993 LPWSTR sendPtr = sendBuf;
994 LPCWSTR endPtr= chatbuf + wcslen(chatbuf);
997 //convertTEXT(indexPtr,chatbuf,indexPtr,endPtr);
999 for(;(chatbuf) <= (endPtr);(chatbuf)++){
1002 wcscpy((sendBuf),L"&");
1003 (sendBuf) += wcslen(sendBuf);
1006 wcscpy((sendBuf),L"<");
1007 (sendBuf) += wcslen(sendBuf);
1010 wcscpy((sendBuf),L">");
1011 (sendBuf) += wcslen(sendBuf);
1014 wcscpy((sendBuf),L""");
1015 (sendBuf) += wcslen(sendBuf);
1018 wcscpy((sendBuf),L"'");
1019 (sendBuf) += wcslen(sendBuf);
1022 sendBuf[0] = chatbuf[0];
1029 WideToMB(CP_UTF8,sendPtr,indexPtr,NICOLIVE_SENDCHATBUFLEN * 4 - (indexPtr - buffer) - 1);
1030 indexPtr += strlen(indexPtr);
1033 strcpy(indexPtr,"</chat>");
1034 indexPtr[strlen(indexPtr)] = '\0';
1039 INT_PTR sendLen = 0;
1040 INT_PTR sentLen = 0;
1041 INT_PTR max = strlen(buffer) + 1;
1044 sendLen = send(self->chatManager.sock,buffer,max - sentLen,0);
1046 } while(sendLen > 0);
1055 WinHttpCloseHandle(hGetPostKeySession);
1057 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1058 LeaveCriticalSection(&self->sessionManager.cs);
1074 //
\83C
\83\93\83\89\83C
\83\93\8aÖ
\90\94
1079 NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P self,LPCWSTR userSession,HINTERNET hConnect,LPVOID buffer){
1081 NLIB_RESULT rslt = NLIB_ERR_OK;
1085 //HINTERNET hWatchLiveNicoSession = NULL;
1086 //HINTERNET hGetPlayerStatusRequest = NULL;
1087 const UINT_PTR buflen = LENGTH_65536;
1089 //LPWSTR sendBuffer;
1090 LPSTR recvBuffer = (LPSTR)buffer;
1093 DWORD statusCodeSize = sizeof(statusCode);
1098 if(WinHttpSendRequest(hConnect,userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1100 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1105 if(WinHttpReceiveResponse(hConnect,NULL) == FALSE){
1107 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1113 if (WinHttpQueryHeaders(hConnect,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1114 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1119 if (HTTP_STATUS_OK != statusCode){
1120 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1125 //recvBuffer = (LPSTR)sendBuffer;
1128 if(ReadHttpBody(hConnect,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
1130 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1135 recvBuffer[readSize] = '\0';
1137 recvBuffer = strstr(recvBuffer,"<");
1139 dumpln_mb(CP_UTF8,"%s",recvBuffer);
1142 XMLParse(self,recvBuffer,NPlayerStatus_ElementStartHandler,NPlayerStatus_ElementEndHandler,NPlayerStatus_CharacterDataHandler);
1144 if(rslt != NLIB_ERR_OK){
1161 #define GETNICOLIVEHIS_OBJNAMELENGTH LENGTH_256
1162 #define GETNICOLIVEHIS_COOKIELENGTH LENGTH_512
1164 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect){
1166 NLIB_RESULT rslt = NLIB_ERR_OK;
1168 EnterCriticalSection(&self->sessionManager.cs);
1170 //HINTERNET hNicoVideoConnect = NULL;
1171 HINTERNET hStreamBrowse = NULL;
1174 WCHAR objectName[GETNICOLIVEHIS_OBJNAMELENGTH] = {L"/watch/"};
1175 WCHAR cookie[GETNICOLIVEHIS_COOKIELENGTH] = {L"Cookie: "};
1177 DWORD statusCodeSize = sizeof(statusCode);
1178 DWORD chunkSize = LENGTH_65536;
1179 LPVOID chunkMemory =self->sessionManager.buffer;
1183 LPWSTR buffer = (LPWSTR)chunkSize;
1187 if((GETNICOLIVEHIS_OBJNAMELENGTH - wcslen(objectName) <= wcslen(self->playerStatus.stream.id)) || GETNICOLIVEHIS_COOKIELENGTH - wcslen(cookie) <= wcslen(self->userSession)){
1189 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1193 wcscat(objectName,self->playerStatus.stream.id);
1194 wcscat(cookie,self->userSession);
1198 //hNicoVideoConnect = hConnect;
1202 hStreamBrowse = WinHttpOpenRequest(hNicoVideoConnect,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1207 if(WinHttpSendRequest(hStreamBrowse,cookie,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1209 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1214 if(WinHttpReceiveResponse(hStreamBrowse,NULL) == FALSE){
1216 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1221 if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1222 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1227 if (HTTP_STATUS_OK != statusCode){
1228 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1234 if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_SET_COOKIE,WINHTTP_HEADER_NAME_BY_INDEX,buffer,&chunkSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1235 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1240 LPWSTR start =wcsstr(buffer,L"nicolivehistory=");
1242 LPWSTR end = wcsstr(start,L";");
1244 UINT_PTR length = end - start;
1246 if(length >= sizeof(self->nicoLiveHistory)){
1247 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1252 wcsncpy(self->nicoLiveHistory,start,length);
1253 self->nicoLiveHistory[length] = L'\0';
1258 WinHttpCloseHandle(hStreamBrowse);
1261 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1262 LeaveCriticalSection(&self->sessionManager.cs);
1278 static unsigned int WINAPI NicoLiveKeapALiveThread(void* lpBuffer){
1280 unsigned int rslt = 0;
1282 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1284 rslt = loopCommon(self,self->chatManager.setKeepAliveTimeEvent,self->chatManager.resetEvents[2],self->chatManager.onKeepAlliveSend);
1291 static unsigned int WINAPI NicoLiveHeartBeatThread(void* lpBuffer){
1293 unsigned int rslt = 0;
1295 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1298 rslt = loopCommon(self,self->chatManager.setHeartBeatTimeEvent,self->chatManager.resetEvents[1],self->chatManager.onHeartBeatSend);
1306 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend){
1308 unsigned int rslt = 0;
1309 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1310 WSAEVENT streamEvent[2] = {self->chatManager.endEvent,sendEvent};
1311 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1316 WSASetEvent(resetEvent);
1318 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1321 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1322 if(dwResult == WSA_WAIT_FAILED){
1328 switch(dwResult - WSA_WAIT_EVENT_0){
1335 WSAResetEvent(resetEvent);
1349 WSAResetEvent(sendEvent);
1350 endResult = WSAWaitForMultipleEvents(sizeof(streamEvent) / sizeof(streamEvent[0]),streamEvent,FALSE,self->chatManager.heartBeatTime,FALSE);
1352 if(endResult == WSA_WAIT_TIMEOUT){
1354 nicoLiveOnSend(self);
1355 //dumpln(TEXT("onSend"));
1359 switch(endResult - WSA_WAIT_EVENT_0){
1382 _beginthread(NicoLiveError,0,self);
1387 static VOID OnSendHeartBeat(NicoLiveStream_P self){
1389 if(self->chatManager.heartBeatFlag){
1390 NicoLiveStream_sendHeartBeat(self);
1395 static VOID OnSendKeepAllive(NicoLiveStream_P self){
1397 if(self->chatManager.keapALiveFlag){
1398 LPCWSTR mail[2] = {L"184",NULL};
1399 NicoLiveStream_sendChat(self,L"/keapalive",mail,NULL);
1404 #define NICOLIVE_RECEVE_CHAT_LENGTH LENGTH_2048
1405 #define NICOLIVE_REQUEST_CHAT_LENGTH LENGTH_256
1406 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer){
1409 unsigned int rslt = 0;
1411 //LPWSTR user_id = NULL;
1412 //LPWSTR name = NULL;
1413 //LPWSTR chatBuf = NULL;
1417 CHAR requestChat[NICOLIVE_REQUEST_CHAT_LENGTH]; //
\91\97\90M
\93d
\95¶
\97p
\83o
\83b
\83t
\83@
1418 LPCSTR sendFormat = "<thread thread=\"%u\" res_from=\"%d\" version=\"20061206\" />"; //
\91\97\90M
\93d
\95¶
\83t
\83H
\81[
\83}
\83b
\83g
1419 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer; //
\83j
\83R
\90¶
\95ú
\91\97\83I
\83u
\83W
\83F
\83N
\83g
1420 INT_PTR sendLen; //
\91\97\90M
\97p
\95¶
\8e\9a\90\94
1421 INT_PTR sentLen; //
\91\97\90M
\8dÏ
\82Ý
\95¶
\8e\9a\90\94
1422 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1423 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1429 WSASetEvent(self->chatManager.resetEvents[0]);
1431 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1434 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1435 if(dwResult == WSA_WAIT_FAILED){
1441 switch(dwResult - WSA_WAIT_EVENT_0){
1448 WSAResetEvent(self->chatManager.resetEvents[0]);
1464 //
\83\
\83P
\83b
\83g
\82Ì
\90Ý
\92è
1465 self->chatManager.sock = GetConectedSocket(self->playerStatus.ms.addr,self->playerStatus.ms.port,SOCK_STREAM,AF_INET,IPPROTO_TCP);
1468 //
\83R
\83\81\83\93\83g
\8eó
\90M
\8aJ
\8en
\82Ì
\89º
\8f\80\94õ
1469 if(self->chatManager.sock == INVALID_SOCKET){
1470 self->error = NLIB_ERR_FAILED_NETWORK;
1479 if(NICOLIVE_REQUEST_CHAT_LENGTH <= _scprintf(sendFormat,self->playerStatus.ms.thread,self->res_from)){
1481 self->error = NLIB_ERR_BUFFER_TOOLITTLE;
1488 sprintf(requestChat,sendFormat,self->playerStatus.ms.thread,self->res_from);
1492 //
\83R
\83\81\83\93\83g
\8eó
\90M
\97v
\8b\81\91\97\90M
\8f\88\97\9d
1496 sendLen = strlen(requestChat) + 1;
1498 len = send(self->chatManager.sock,requestChat,sendLen,0);
1499 if(len == SOCKET_ERROR){
1500 self->error = NLIB_ERR_FAILED_NETWORK;
1508 }while(sentLen < sendLen);
1512 if(NicoLiveRecvChatLoop(self) == FALSE){
1524 _beginthread(NicoLiveError,0,self);
1530 closesocket(self->chatManager.sock);
1545 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self){
1549 //
\83R
\83\81\83\93\83g
\8eó
\90M
\8f\88\97\9d
1551 BOOL rslt = TRUE; //
\8c\8b\89Ê
1552 LPWSTR commentBuf = NULL; //
\83R
\83\81\83\93\83g
\83o
\83b
\83t
\83@
1553 LPWSTR* mailCountBuf = NULL; //
\83\81\81[
\83\8b\83|
\83C
\83\93\83^
\83o
\83b
\83t
\83@
1554 INT_PTR recevedLen; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\92·
1555 INT_PTR messageBufLen; //
\83o
\83b
\83t
\83@
\92·
1559 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ñ
1560 WSANETWORKEVENTS netEvents; //
\83l
\83b
\83g
\83\8f\81[
\83N
\83C
\83x
\83\93\83g
1561 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
1564 SIZE_T commentBufSize = sizeof(WCHAR) * LENGTH_2048; //
\83R
\83\81\83\93\83g
\83o
\83b
\83t
\83@
\92·
1565 SIZE_T mailCountBufSize = sizeof(LPWSTR) * LENGTH_256; //
\83\81\81[
\83\8b\82Ì
\83|
\83C
\83\93\83^
\97p
\83o
\83b
\83t
\83@
\92·
1568 WSAEVENT hRecvEvent = NULL;
1570 //
\8eó
\90M
\8f\80\94õ
\8f\88\97\9d
1571 self->chatManager.commentCountSum = 0;
1572 hRecvEvent = WSACreateEvent();
1573 self->chatManager.recvBuf[0] = '\0';
1574 WSAEventSelect(self->chatManager.sock, hRecvEvent, FD_READ | FD_CLOSE);
1575 hEventArray[0] = hRecvEvent;
1576 hEventArray[1] = self->chatManager.endEvent;
1578 commentBuf = (LPWSTR)malloc(commentBufSize);
1579 mailCountBuf = (LPWSTR*)malloc(mailCountBufSize);
1581 //
\90Ø
\92f
\82³
\82ê
\82é
\82Ü
\82Å
\83\8b\81[
\83v
1586 //
\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é
1587 messageBufLen = strlen(self->chatManager.recvBuf);
1589 //
\8eó
\90M
\82©
\8fI
\97¹
\83C
\83x
\83\93\83g
\82ð
\8c\9f\92m
\82·
\82é
\82Ü
\82Å
\91Ò
\8b@
1590 dwResult = WSAWaitForMultipleEvents(sizeof(hEventArray) / sizeof(hEventArray[0]),hEventArray,FALSE,WSA_INFINITE,FALSE);
1592 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1593 if(dwResult == WSA_WAIT_FAILED){
1600 //
\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
1601 if(dwResult - WSA_WAIT_EVENT_0 == 0){
1603 WSAEnumNetworkEvents(self->chatManager.sock,hRecvEvent,&netEvents);
1605 //
\93Ç
\8eæ
\83C
\83x
\83\93\83g
\82Ì
\8fê
\8d\87\83R
\83\81\83\93\83g
\82ð
\8eó
\90M
\82·
\82é
1606 if(netEvents.lNetworkEvents & FD_READ){
1609 recevedLen = recv(self->chatManager.sock,&self->chatManager.recvBuf[messageBufLen],(sizeof(self->chatManager.recvBuf) - 1) - messageBufLen ,0);
1611 if(recevedLen == SOCKET_ERROR){
1612 self->error = NLIB_ERR_FAILED_NETWORK;
1617 self->chatManager.recvBuf[messageBufLen + recevedLen] = '\0';
1624 NicoLiveParseComment(self,commentBuf,messageBufLen + recevedLen,mailCountBuf,&mailCountBufSize,&commentBufSize);
1630 } else if(netEvents.lNetworkEvents && FD_CLOSE){
1634 }//if(netEvents.lNetworkEvents & FD_READ)
1636 } else if(dwResult - WSA_WAIT_EVENT_0 == 1){
1640 }//if(dwResult - WSA_WAIT_EVENT_0 == 0)
1652 WSACloseEvent(hRecvEvent);
1660 static VOID NicoLiveParseComment(NicoLiveStream_P self,LPWSTR commentBuf,UINT_PTR endSize,LPWSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize){
1662 LPWSTR indexPtr; //
\89ð
\90Í
\8e\9e\82Ì
\8ew
\95W
\83|
\83C
\83\93\83^
1663 NicoLiveChat nicoLiveChat; //
\83`
\83\83\83b
\83g
\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1664 NicoLiveThreadComment nicoLiveThreadComment; //
\90Ú
\91±
\89\9e\93\9a\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1665 NicoLiveSendResultComment nicoLiveSendResultComment; //
\91\97\90M
\89\9e\93\9a\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1666 NicoLiveChat nicoLiveChatBase; //
\83`
\83\83\83b
\83g
\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1667 NicoLiveThreadComment nicoLiveThreadCommentBase; //
\90Ú
\91±
\89\9e\93\9a\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1668 NicoLiveSendResultComment nicoLiveSendResultCommentBase;//
\91\97\90M
\89\9e\93\9a\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1669 LPWSTR attrNameStart; //
\91®
\90«
\96¼
\8aJ
\8en
\83|
\83C
\83\93\83^
1670 LPWSTR attrNameEnd; //
\91®
\90«
\96¼
\8fI
\97¹
\83|
\83C
\83\93\83^
1671 LPWSTR attrValueStart; //
\91®
\90«
\92l
\8aJ
\8en
\83|
\83C
\83\93\83^
1672 LPWSTR attrValueEnd; //
\91®
\90«
\92l
\8fI
\97¹
\83|
\83C
\83\93\83^
1673 INT_PTR nameLen; //
\91®
\90«
\82Ì
\96¼
\91O
\82Ì
\92·
\82³
1674 LPWSTR mailIndexPtr; //
\83\81\81[
\83\8b\91®
\90«
\92l
\89ð
\90Í
\97p
\8ew
\95W
\83|
\83C
\83\93\83^
1675 LPWSTR xmlTextPtr; //xml
\83e
\83L
\83X
\83g
\8c`
\8e®
\82Ì
\83f
\81[
\83^
\89ð
\90Í
\8e\9e\82É
\8eg
\97p
\82·
\82é
\83|
\83C
\83\93\83^
1676 LPWSTR xmlTextEnd; //xml
\83e
\83L
\83X
\83g
\8fI
\97¹
\83|
\83C
\83\93\83^
1677 LPWSTR* mailIndex; //
\83\81\81[
\83\8b\83R
\83}
\83\93\83h
\83\8a\83X
\83g
\83|
\83C
\83\93\83^
1678 BOOL isReceveChat = FALSE; //
\83`
\83\83\83b
\83g
\8eó
\90M
\83t
\83\89\83O
1679 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³
1680 LPSTR recvBufTmp; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\91\80\8dì
\97p
\83|
\83C
\83\93\83^
1681 LPSTR recvEndPoint; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\8fI
\92[
\83|
\83C
\83\93\83^
1685 recvBufTmp = &self->chatManager.recvBuf[0];
1686 recvEndPoint = &self->chatManager.recvBuf[endSize];
1689 //
\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
\8f\89\8aú
\89»
1690 nicoLiveChatBase.anonymity = L"";
1691 nicoLiveChatBase.chatBuf = L"";
1692 nicoLiveChatBase.date = L"";
1693 nicoLiveChatBase.locale = L"";
1694 nicoLiveChatBase.mail = mailCountBuf;
1695 nicoLiveChatBase.name = L"";
1696 nicoLiveChatBase.no = L"";
1697 nicoLiveChatBase.premium = L"";
1698 nicoLiveChatBase.thread = L"";
1699 nicoLiveChatBase.user_id = L"";
1700 nicoLiveChatBase.vpos = L"";
1701 nicoLiveChatBase.mailCount = 0;
1705 nicoLiveThreadCommentBase.last_res = L"";
1706 nicoLiveThreadCommentBase.thread = L"";
1707 nicoLiveThreadCommentBase.ticket = L"";
1710 nicoLiveSendResultCommentBase.no = L"";
1711 nicoLiveSendResultCommentBase.status = L"";
1712 nicoLiveSendResultCommentBase.thread = L"";
1715 //
\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é
1716 for (;recvBufTmp + strlen(recvBufTmp) < recvEndPoint;recvBufTmp += strlen(recvBufTmp) + 1){
1719 commentSizeCh = sizeof(WCHAR) * GetLenToWide(CP_UTF8,recvBufTmp);
1720 extendMalloc(commentBuf,LPWSTR,*commentBufSize,commentSizeCh);
1721 MBToWide(CP_UTF8,recvBufTmp,commentBuf,*commentBufSize);
1723 traceln(TEXT("comment:\r\n%s"),commentBuf);
1724 //thread
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1725 if((indexPtr = wcsstr(commentBuf,L"<thread ")) != NULL){
1727 indexPtr += wcslen(L"<thread ");
1728 skipXMLSPACE(indexPtr);
1733 nicoLiveThreadComment = nicoLiveThreadCommentBase;
1735 while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1736 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1739 nameLen = attrNameEnd - attrNameStart;
1740 if(wcsncmp(attrNameStart,L"ticket",nameLen) == 0){
1743 partString(nicoLiveThreadComment.ticket,attrValueStart,attrValueEnd);
1744 wcscpy(self->ticket,nicoLiveThreadComment.ticket);
1746 } else if(wcsncmp(attrNameStart,L"last_res",nameLen) == 0){
1748 partString(nicoLiveThreadComment.last_res,attrValueStart,attrValueEnd);
1751 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1753 partString(nicoLiveThreadComment.thread,attrValueStart,attrValueEnd);
1754 } else if(wcsncmp(attrNameStart,L"server_time",nameLen) == 0){
1756 NicoLiveStream_setVpos((*self),attrValueStart);
1758 partString(nicoLiveThreadComment.server_time,attrValueStart,attrValueEnd);
1761 skipXMLSPACE(indexPtr);
1766 self->callBack(NICOLIVE_EVENT_RECEVE_CONNECTRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveThreadComment,self->chatManager.chatNo);
1768 //chat
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1769 } else if((indexPtr = wcsstr(commentBuf,L"<chat ")) != NULL){
1771 indexPtr += wcslen(L"<chat ");
1772 skipXMLSPACE(indexPtr);
1777 nicoLiveChat = nicoLiveChatBase;
1779 while(wcsncmp(indexPtr,L">",wcslen(L">"))){
1781 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1783 nameLen = attrNameEnd - attrNameStart;
1786 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1788 partString(nicoLiveChat.no,attrValueStart,attrValueEnd);
1790 } else if(wcsncmp(attrNameStart,L"date",nameLen) == 0){
1792 NicoLiveStream_setVpos((*self),attrValueStart);
1794 partString(nicoLiveChat.date,attrValueStart,attrValueEnd);
1796 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1798 partString(nicoLiveChat.thread,attrValueStart,attrValueEnd);
1800 } else if(wcsncmp(attrNameStart,L"premium",nameLen) == 0){
1802 partString(nicoLiveChat.premium,attrValueStart,attrValueEnd);
1804 } else if(wcsncmp(attrNameStart,L"anonymity",nameLen) == 0){
1806 partString(nicoLiveChat.anonymity,attrValueStart,attrValueEnd);
1809 } else if(wcsncmp(attrNameStart,L"locale",nameLen) == 0){
1811 partString(nicoLiveChat.locale,attrValueStart,attrValueEnd);
1813 } else if(wcsncmp(attrNameStart,L"vpos",nameLen) == 0){
1815 partString(nicoLiveChat.vpos,attrValueStart,attrValueEnd);
1817 } else if(wcsncmp(attrNameStart,L"user_id",nameLen) == 0){
1819 partString(nicoLiveChat.user_id,attrValueStart,attrValueEnd);
1821 } else if(wcsncmp(attrNameStart,L"name",nameLen) == 0){
1823 partString(nicoLiveChat.name,attrNameStart,attrValueEnd);
1825 } else if(wcsncmp(attrNameStart,L"mail",nameLen) == 0){
1827 nicoLiveChat.mailCount = 1;
1830 for(mailIndexPtr = attrValueStart;mailIndexPtr <= attrValueEnd;mailIndexPtr++){
1832 if(mailIndexPtr[0] == L' '){
1834 nicoLiveChat.mailCount++;
1840 extendMalloc(mailCountBuf,LPWSTR*,*mailCountBufSize,nicoLiveChat.mailCount);
1842 nicoLiveChat.mail = mailCountBuf;
1843 mailCountBuf[0] = NULL;
1845 for(mailIndex = mailCountBuf,mailIndexPtr = attrValueStart,mailIndex[0] = mailIndexPtr;mailIndexPtr < attrValueEnd;mailIndexPtr++){
1848 if(mailIndexPtr[0] == L' '){
1850 mailIndex[0] = mailIndexPtr + 1;
1851 mailIndexPtr[0] = L'\0';
1858 mailIndexPtr[0] = L'\0';
1862 skipXMLSPACE(indexPtr);
1866 xmlTextPtr = indexPtr;
1867 xmlTextEnd = wcsstr(indexPtr,L"<");
1868 convertXMLTEXT(nicoLiveChat.chatBuf,indexPtr,xmlTextPtr,xmlTextEnd);
1872 self->chatManager.chatNo = wcstoul(nicoLiveChat.no,NULL,10);
1876 self->chatManager.commentCountSum++;
1877 isReceveChat = TRUE;
1879 check((_heapchk() == _HEAPOK),TEXT("
\83q
\81[
\83v
\83G
\83\89\81[
\82Å
\82·"));
1881 if((wcscmp(nicoLiveChat.chatBuf,L"/disconnect") == 0 && wcscmp(nicoLiveChat.premium,L"2") == 0)){
1884 _beginthread(NicoLiveSelfDisconnect,0,self);
1886 self->callBack(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&nicoLiveChat,self->chatManager.commentCountSum);
1889 //chat_result
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1890 } else if((indexPtr = wcsstr(commentBuf,L"<chat_result ")) != NULL){
1892 indexPtr += wcslen(L"<chat_result ");
1894 nicoLiveSendResultComment = nicoLiveSendResultCommentBase;
1896 while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1897 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1900 nameLen = attrNameEnd - attrNameStart;
1901 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1904 partString(nicoLiveSendResultComment.no,attrValueStart,attrValueEnd);
1906 } else if(wcsncmp(attrNameStart,L"status",nameLen) == 0){
1908 partString(nicoLiveSendResultComment.status,attrValueStart,attrValueEnd);
1911 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1913 partString(nicoLiveSendResultComment.thread,attrValueStart,attrValueEnd);
1916 skipXMLSPACE(indexPtr);
1919 //
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\83\8a\83Z
\83b
\83g
1920 WSAResetEvent(self->chatManager.setKeepAliveTimeEvent);
1922 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSENDRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveSendResultComment,(NICOLIVE_PARAM)NULL);
1928 if(recvBufTmp == recvEndPoint && isReceveChat){
1929 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSETTLE,self,self->option,self->chatManager.chatNo,self->chatManager.commentCountSum);
1935 strcpy(&self->chatManager.recvBuf[0],recvBufTmp);
1952 static void NicoLiveError(void *buf){
1954 NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1956 nl->callBack(NICOLIVE_EVENT_ERR_CONNECT,nl,nl->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
1958 NicoLiveStream_disConnect(nl);
1966 static void NicoLiveSelfDisconnect(void *buf){
1968 NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1970 dumpln(TEXT("selfdisconnect"),);
1972 NicoLiveStream_disConnect(nl);
1982 static INLINE SOCKET GetConectedSocket(LPCWSTR nordName,LPCWSTR port,int socktype,int addr_famiry,int protocol){
1985 SOCKET rslt = INVALID_SOCKET;
1988 PADDRINFOW res,res0;
1990 ZeroMemory(&hints,sizeof(hints));
1991 hints.ai_socktype = socktype;
1992 hints.ai_family = addr_famiry;
1993 hints.ai_protocol = protocol;
1994 GetAddrInfoW(nordName,port,&hints,&res0);
1997 for(res = res0; res != NULL;res = res->ai_next){
2002 rslt = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
2003 if(rslt == INVALID_SOCKET){
2016 if(connect(rslt,res->ai_addr,(int)res->ai_addrlen) == SOCKET_ERROR){
2031 rslt = INVALID_SOCKET;
2035 //res
\8d\
\91¢
\91Ì
\89ð
\95ú