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,LPCTSTR 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);
108 #ifdef USE_NLIB_KEEPALIVE
111 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\91\97\90M
\83\8b\81[
\83v
\8aÖ
\90\94
113 static unsigned int WINAPI NicoLiveKeapALiveThread(void* lpBuffer);
115 #endif //USE_NLIB_KEEPALIVE
121 ///
\83`
\83\83\83b
\83g
\8eó
\90M
\83\8b\81[
\83v
\8aÖ
\90\94
123 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self);
128 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend,LPDWORD time);
131 ///
\83R
\83\81\83\93\83g
\89ð
\90Í
\8aÖ
\90\94
133 static VOID NicoLiveParseComment(NicoLiveStream_P self,LPTSTR commentBuf,UINT_PTR endSize,LPTSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize);
135 static void NicoLiveError(void *buf);
137 static void NicoLiveSelfDisconnect(void *buf);
139 static VOID OnSendHeartBeat(NicoLiveStream_P self);
141 static VOID OnSendKeepAllive(NicoLiveStream_P self);
143 ///
\83\
\83P
\83b
\83g
\8eæ
\93¾
\8aÖ
\90\94
145 static INLINE SOCKET GetConectedSocket(LPCTSTR nordName,LPCTSTR port,int socktype,int addr_famiry,int protocol);
148 StreamStatus_P NicoLiveStream_getStreamStatus(NicoLiveStream_P self){
150 return &self->playerStatus.stream;
153 BOOL Initialize_NicoLive(){
159 //
\83n
\81[
\83g
\83r
\81[
\83g
\83R
\83\93\83e
\83i
\8f\89\8aú
\89»
160 ZeroMemory(&heartBeatContainer,sizeof(heartBeatContainer));
161 heartBeatContainer.is_restrictSize = sizeof(TCHAR) * LENGTH_1024;
162 heartBeatContainer.is_restrictBuff = (LPTSTR)calloc(1,heartBeatContainer.is_restrictSize);
163 heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
165 heartBeatContainer.ticketSize = sizeof(TCHAR) * LENGTH_1024;
166 heartBeatContainer.ticketBuff = (LPTSTR)calloc(1,heartBeatContainer.ticketSize);
167 heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
169 InitializeCriticalSection(&heartBeatCs);
179 extern BOOL Finalize_NicoLive(){
182 DeleteCriticalSection(&heartBeatCs);
184 //
\83p
\81[
\83T
\8cã
\8f\88\97\9d
185 free(heartBeatContainer.is_restrictBuff);
186 free(heartBeatContainer.ticketBuff);
200 NicoLiveStream_P NicoLiveStream_new(){
201 //
\90¶
\90¬&
\8f\89\8aú
\89»
202 NicoLiveStream_P self = (NicoLiveStream_P)calloc(1,sizeof(NicoLiveStream));
204 //
\8f\89\8aú
\92l
\82Ì
\90Ý
\92è
205 self->chatManager.onHeartBeatSend = OnSendHeartBeat;
209 InitializeCriticalSection(&self->sessionManager.cs);
211 self->chatManager.heartBeatTime = 60000;
213 self->chatManager.heartBeatFlag = TRUE;
217 self->isConnecting = FALSE;
219 self->chatManager.endEvent = WSACreateEvent();
221 self->chatManager.startEvent = WSACreateEvent();
223 self->chatManager.deleteEvent = WSACreateEvent();
225 self->chatManager.setHeartBeatTimeEvent = WSACreateEvent();
228 #ifdef USE_NLIB_KEEPALIVE
230 self->chatManager.onKeepAlliveSend = OnSendKeepAllive;
232 self->chatManager.keepAliveTime = 900000;
234 self->chatManager.keapALiveFlag = FALSE;
236 self->chatManager.setKeepAliveTimeEvent = WSACreateEvent();
238 self->chatManager.resetEvents[KEEPALLIVERESETEVENT] = WSACreateEvent();
240 #endif //USE_NLIB_KEEPALIVE
242 self->chatManager.resetEvents[0] = WSACreateEvent();
244 self->chatManager.resetEvents[1] = WSACreateEvent();
252 //
\83X
\83\8c\83b
\83h
\82Ì
\8aJ
\8en
253 self->chatManager.hRecvChatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveRecvChat,self,0,&self->chatManager.recvChatThreadID);
255 self->chatManager.hHeartBeatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveHeartBeatThread,self,0,&self->chatManager.heartBeatThreadID);
257 #ifdef USE_NLIB_KEEPALIVE
258 self->chatManager.hKeapALiveHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveKeapALiveThread,self,0,&self->chatManager.keapALiveThreadID);
267 //
\83j
\83R
\83j
\83R
\90¶
\95ú
\91\97\8aÖ
\98A
\8aÖ
\90\94
268 ///////////////////////////////////////////////////
270 VOID NicoLiveStream_delete(NicoLiveStream_P* self){
272 NicoLiveStream_disConnect((*self));
274 WSASetEvent((*self)->chatManager.deleteEvent);
276 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hRecvChatHandle){
277 WaitForSingleObject( (*self)->chatManager.hRecvChatHandle, INFINITE );
278 CloseHandle((*self)->chatManager.hRecvChatHandle);
281 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hHeartBeatHandle){
283 WaitForSingleObject((*self)->chatManager.hHeartBeatHandle,INFINITE);
284 CloseHandle((*self)->chatManager.hHeartBeatHandle);
287 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hKeapALiveHandle){
289 WaitForSingleObject((*self)->chatManager.hKeapALiveHandle,INFINITE);
290 CloseHandle((*self)->chatManager.hKeapALiveHandle);
300 //
\8cã
\8f\88\97\9d&
\94j
\8aü
302 DeleteCriticalSection(&(*self)->sessionManager.cs);
304 WSACloseEvent((*self)->chatManager.setHeartBeatTimeEvent);
305 #ifdef USE_NLIB_KEEPALIVE
306 WSACloseEvent((*self)->chatManager.setKeepAliveTimeEvent);
307 WSACloseEvent((*self)->chatManager.resetEvents[KEEPALLIVERESETEVENT]);
309 WSACloseEvent((*self)->chatManager.endEvent);
311 WSACloseEvent((*self)->chatManager.startEvent);
313 WSACloseEvent((*self)->chatManager.deleteEvent);
315 WSACloseEvent((*self)->chatManager.resetEvents[0]);
317 WSACloseEvent((*self)->chatManager.resetEvents[1]);
326 (*self) = (NicoLiveStream_P)NULL;
333 ///
\83n
\81[
\83g
\83r
\81[
\83g
\82Ì
\8aÔ
\8au
\82ð
\90Ý
\92è
\81i
\83~
\83\8a\95b)
335 VOID NicoLiveStream_setHeartBeatMsec(NicoLiveStream_P self,DWORD msec){
338 self->chatManager.heartBeatTime = msec;
339 WSASetEvent(self->chatManager.setHeartBeatTimeEvent);
344 ///
\83n
\81[
\83g
\83r
\81[
\83g
\82Ì
\8aÔ
\8au
\82ð
\8eæ
\93¾(
\83~
\83\8a\95b)
346 DWORD NicoLiveStream_getHeartBeatMsec(NicoLiveStream_P self){
348 return self->chatManager.heartBeatTime;
354 ///
\83n
\81[
\83g
\83r
\81[
\83g
\97L
\8cø
\81E
\96³
\8cø
\90Ý
\92è
356 VOID NicoLiveStream_setHeartBeatFlag(NicoLiveStream_P self,BOOL flag){
358 self->chatManager.heartBeatFlag = flag;
364 ///
\83n
\81[
\83g
\83r
\81[
\83g
\97L
\8cø
\83t
\83\89\83O
\8eæ
\93¾
366 BOOL NicoLiveStream_getHeartBeatFlag(NicoLiveStream_P self){
368 return self->chatManager.heartBeatFlag;
375 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\82Ì
\8aÔ
\8au
\82ð
\90Ý
\92è(
\83~
\83\8a\95b)
377 VOID NicoLiveStream_setKeapALiveMsec(NicoLiveStream_P self,DWORD msec){
379 #ifdef USE_NLIB_KEEPALIVE
380 self->chatManager.keepAliveTime = msec;
381 WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
388 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\82Ì
\8aÔ
\8au
\82ð
\8eæ
\93¾(
\83~
\83\8a\95b)
390 DWORD NicoLiveStream_getKeapALiveMsec(NicoLiveStream_P self){
392 #ifdef USE_NLIB_KEEPALIVE
393 return self->chatManager.keepAliveTime;
402 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\97L
\8cø
\81E
\96³
\8cø
\90Ý
\92è
404 VOID NicoLiveStream_setKeapALiveFlag(NicoLiveStream_P self,BOOL flag){
406 #ifdef USE_NLIB_KEEPALIVE
407 self->chatManager.keapALiveFlag = flag;
413 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\83t
\83\89\83O
\8eæ
\93¾
415 BOOL NicoLiveStream_getKeapALiveFlag(NicoLiveStream_P self){
417 #ifdef USE_NLIB_KEEPALIVE
418 return self->chatManager.keapALiveFlag;
425 VOID NicoLiveStrream_setResFrom(NicoLiveStream_P self,INT_PTR res){
429 self->res_from = (res < 0 || res > 1000) ? 0 : ((-1) * res);
433 INT_PTR NicoLiveStream_getResFrom(NicoLiveStream_P self){
435 return (-1) * self->res_from;
438 NLIB_RESULT NicoLiveStream_connect(NicoLiveStream_P self,NicoVideoAuth_P nicoVideoAuth,LPCTSTR url,NicoRecvCallBack callback,LPVOID option){
440 #define NICOLIVE_CONNECTIONSTREAM_COOKIE_COUNT 1
441 #define LIVENO_LENGTH LENGTH_NICOLIVEID
443 NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
451 //url
\82©
\82ç
\90Ú
\91±
\94Ô
\8d\86\82ð
\92\8a\8fo
452 LPCTSTR pInputLiveNo = url;
453 LPCTSTR psrech = wcsstr(url,L"http://");
454 LPTSTR pInputLiveNoEnd;
455 TCHAR liveNo[LIVENO_LENGTH] = {0};
458 if(self == NULL)goto end;
460 BOOL sleepFlag = self->isConnecting;
462 //
\91O
\82É
\82Â
\82È
\82¢
\82Å
\82¢
\82½
\95ú
\91\97\82ð
\90Ø
\92f
463 NicoLiveStream_disConnect(self);
465 if(sleepFlag == TRUE){
473 for(;psrech != NULL;psrech = wcsstr(psrech +1,L"/")){
475 pInputLiveNo = psrech + 1;
482 _tcstol(pInputLiveNo + 2,&pInputLiveNoEnd,10);
484 if(pInputLiveNo == NULL){
486 rslt = NLIB_LIVENO_IS_NULL;
489 }else if(pInputLiveNoEnd - pInputLiveNo + 2 >= LIVENO_LENGTH - 1){
491 rslt = NLIB_LIVENO_FAILED_TOOBIG;
494 } else if((wcsncmp(pInputLiveNo,TEXT("lv"),2) == 0)||(( wcsncmp(pInputLiveNo,TEXT("co"),2) == 0) || (wcsncmp(pInputLiveNo,TEXT("ch"),2) == 0) )){
497 wcsncpy(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
500 } else if(_wtoi(pInputLiveNo) != 0){
502 wcscpy(liveNo,L"lv");
503 wcsncat(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
507 rslt = NLIB_LIVENO_FAILED_UNDEFEINE;
516 wcsncpy(self->userSession,L"Cookie: ",sizeof(self->userSession) / sizeof(self->userSession[0]) - 1);
517 wcsncat(self->userSession,nicoVideoAuth->userSession,sizeof(self->userSession) / sizeof(self->userSession[0]) - 1);
518 self->userSession[sizeof(self->userSession) / sizeof(self->userSession[0]) - 1] = L'\0';
524 TCHAR objectName[LENGTH_256] = {L"api/getplayerstatus?v="};
525 wcsncat(objectName,liveNo,sizeof(objectName) / sizeof(objectName[0]));
530 self->sessionManager.getPlayerStatusSession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",objectName,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
536 //
\83v
\83\8c\83C
\83\84\81[
\83X
\83e
\81[
\83^
\83X
\8eæ
\93¾
537 EnterCriticalSection(&self->sessionManager.cs);
538 rslt = GetPlayerStatus(&self->playerStatus,self->userSession,self->sessionManager.getPlayerStatusSession,self->sessionManager.buffer);
541 LeaveCriticalSection(&self->sessionManager.cs);
543 if(rslt != NLIB_ERR_OK){
550 //
\90¶
\95ú
\91\97\83I
\83u
\83W
\83F
\83N
\83g
\82É
\8ae
\88ø
\90\94\82ð
\90Ý
\92è
552 self->callBack = callback;
553 self->option = option;
556 WSASetEvent(self->chatManager.startEvent);
558 self->isConnecting = TRUE;
571 NLIB_RESULT NicoLiveStream_sendHeartBeat(NicoLiveStream_P self){
574 NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
576 if(self->isConnecting == FALSE){
577 rslt = NLIB_ERR_NOT_LIVECONNECT;
580 if(self == NULL || self->playerStatus.error != NLIB_ERR_OK){
582 rslt = NLIB_ERR_PLAYERSTATUS_ERROR;
588 EnterCriticalSection(&self->sessionManager.cs);
591 const UINT_PTR buflen = LENGTH_65536;
592 LPVOID buffer = self->sessionManager.buffer;
594 LPTSTR objectName = (LPTSTR)buffer;
596 //LPTSTR sendBuffer = (LPTSTR)&objectName[LENGTH_4096];
597 LPSTR recvBuffer = (LPSTR)&objectName[LENGTH_4096];
600 DWORD statusCodeSize = sizeof(statusCode);
602 wcscpy(objectName,L"/api/heartbeat?v=");
603 indexPtr = objectName + wcslen(objectName);
604 wcscpy(indexPtr,self->playerStatus.stream.id);
608 if(self->sessionManager.heartBeatSession == NULL){
609 self->sessionManager.heartBeatSession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",objectName,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
612 if(WinHttpSendRequest(self->sessionManager.heartBeatSession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
614 rslt = NLIB_ERR_FAILED_NETWORK;
619 if(WinHttpReceiveResponse(self->sessionManager.heartBeatSession,NULL) == FALSE){
621 rslt = NLIB_HEARTBEAT_FAILED_CONNECT;
627 if (WinHttpQueryHeaders(self->sessionManager.heartBeatSession,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
628 rslt = NLIB_HEARTBEAT_FAILED_CONNECT;
633 if (HTTP_STATUS_OK != statusCode){
634 rslt = NLIB_HEARTBEAT_FAILED_CONNECT;
639 //recvBuffer = (LPSTR)sendBuffer;
642 if(ReadHttpBody(self->sessionManager.heartBeatSession,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
644 rslt = NLIB_HEARTBEAT_FAILED_CONNECT;
652 EnterCriticalSection(&heartBeatCs);
654 XMLParse(&heartBeatContainer,recvBuffer,NicoLiveHeartBeat_ElementStartHandler,NicoLiveHeartBeat_ElementEndHandler,NicoLiveHeartBeat_CharacterDataHandler);
656 self->chatManager.baseVpos = getBaseVpos(heartBeatContainer.heartBeat.time, self->playerStatus.stream.base_time);
657 setMsec(self->chatManager.commentStartTime);
659 self->callBack(NICOLIVE_EVENT_SEND_HEARTBEAT,self,self->option,(NICOLIVE_PARAM)&heartBeatContainer.heartBeat,(NICOLIVE_PARAM)NULL);
661 ZeroMemory(&heartBeatContainer.heartBeat,sizeof(heartBeatContainer.heartBeat));
663 ZeroMemory(heartBeatContainer.is_restrictBuff,heartBeatContainer.is_restrictSize);
665 ZeroMemory(heartBeatContainer.ticketBuff,heartBeatContainer.ticketSize);
667 heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
669 heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
671 LeaveCriticalSection(&heartBeatCs);
678 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
679 LeaveCriticalSection(&self->sessionManager.cs);
691 VOID NicoLiveStream_disConnect(NicoLiveStream_P self){
693 if(self == NULL || self->isConnecting == FALSE)goto end;
695 DWORD waitRslt = WSA_WAIT_TIMEOUT;
698 while(WSAResetEvent(self->chatManager.startEvent) == FALSE);
699 while(WSASetEvent(self->chatManager.endEvent)== FALSE);
705 waitRslt = WSAWaitForMultipleEvents(sizeof(self->chatManager.resetEvents) / sizeof(self->chatManager.resetEvents[0]),self->chatManager.resetEvents,TRUE,3000,FALSE);
706 } while(waitRslt == WSA_WAIT_TIMEOUT);
709 //nicoLiveStream_Initialize(*self);
710 ZeroMemory(&self->playerStatus,sizeof(self->playerStatus));
711 WSAResetEvent(self->chatManager.endEvent);
713 WinHttpCloseHandle(self->sessionManager.getPlayerStatusSession);
714 self->sessionManager.getPlayerStatusSession = NULL;
715 WinHttpCloseHandle(self->sessionManager.heartBeatSession);
716 self->sessionManager.heartBeatSession = NULL;
720 self->isConnecting = FALSE;
733 #define NICOLIVE_SENDCHATBUFLEN LENGTH_4096
734 #define NICOLIVE_SENDFORMAT "<chat thread=\"%d\" ticket=\"%S\" postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
736 NLIB_RESULT NicoLiveStream_sendChat(NicoLiveStream_P self,LPCTSTR chatbuf,LPCTSTR *mail,LPCTSTR *extends){
738 NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
739 EnterCriticalSection(&self->sessionManager.cs);
742 const UINT_PTR buflen = LENGTH_65536 * 4;
743 LPVOID chunk = self->sessionManager.buffer;
746 LPSTR postKeyBuf = (LPSTR)chunk;
747 LPTSTR postKeyReqBuf = (LPTSTR)&postKeyBuf[NICOLIVE_SENDCHATBUFLEN];
748 LPTSTR cookieBuf = &postKeyReqBuf[NICOLIVE_SENDCHATBUFLEN];
750 DWORD statusCodeSize = sizeof(statusCode);
753 //HINTERNET hWatchLiveNicoVideo = NULL;
754 HINTERNET hGetPostKeySession = NULL;
757 if(self->isConnecting == FALSE){
758 rslt = NLIB_ERR_NOT_LIVECONNECT;
761 if(chatbuf == NULL || wcslen(chatbuf) >= LENGTH_1024){
763 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
770 _swprintf(postKeyReqBuf,L"api/getpostkey?thread=%u&block_no=%u",self->playerStatus.ms.thread,self->chatManager.chatNo / 100);
772 //hWatchLiveNicoVideo = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
773 hGetPostKeySession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",postKeyReqBuf,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
776 //_swprintf(cookieBuf,L"Cookie: %s; %s",self->userSession,self->nicoLiveHistory);
777 _swprintf(cookieBuf,L"Cookie: %s",self->userSession);
779 if(WinHttpSendRequest(hGetPostKeySession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
781 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
787 if(WinHttpReceiveResponse(hGetPostKeySession,NULL) == FALSE){
789 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
795 if (WinHttpQueryHeaders(hGetPostKeySession,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
796 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
801 if (HTTP_STATUS_OK != statusCode){
802 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
810 if(ReadHttpBody(hGetPostKeySession,(LPBYTE)postKeyBuf,buflen,&readSize) == FALSE){
812 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
816 postKeyBuf[readSize] = '\0';
817 postKey = strstr(postKeyBuf,"=") + 1;
821 LPSTR buffer = (LPSTR)&cookieBuf[NICOLIVE_SENDCHATBUFLEN];
826 //mail
\83R
\83}
\83\93\83h
\8dì
\90¬
827 if(mail == NULL || mail[0] == NULL){
833 mailBuf = (LPSTR)postKeyReqBuf;
835 strcpy(indexPtr,"mail=\"");
836 indexPtr += strlen(indexPtr);
838 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
839 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
840 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
846 WideToMB(CP_UTF8,mail[0],indexPtr,len);
847 indexPtr += strlen(indexPtr);
850 for(mail++;mail[0] != NULL;mail++){
855 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
857 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
858 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
863 WideToMB(CP_UTF8,mail[0],indexPtr,len);
864 indexPtr += strlen(indexPtr);
868 strcpy(indexPtr,"\"");
875 //
\8ag
\92£
\91®
\90«
\8dì
\90¬
876 if(extends == NULL || extends[0] == NULL){
882 extendBuf =(LPSTR)cookieBuf;
883 indexPtr = extendBuf;
886 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
888 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
889 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
893 WideToMB(CP_UTF8,extends[0],indexPtr,len);
895 indexPtr += strlen(indexPtr);
897 strcpy(indexPtr,"=\"");
898 indexPtr += strlen(indexPtr);
901 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
903 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
904 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
908 WideToMB(CP_UTF8,extends[1],indexPtr,len);
911 for(extends+= 2;extends[0] != NULL;extends+=2){
916 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
918 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
919 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
923 WideToMB(CP_UTF8,extends[0],indexPtr,len);
925 indexPtr += strlen(indexPtr);
931 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
933 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
934 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
938 WideToMB(CP_UTF8,extends[1],indexPtr,len);
943 indexPtr += strlen(indexPtr);
944 strcpy(indexPtr,"\"");
950 //
\83`
\83\83\83b
\83g
\91\97\90M
\83R
\83\81\83\93\83g
\8dì
\90¬
953 //
\96{
\93\96\82Í
\82±
\82¤
\82µ
\82½
\82¢:"<chat thread=\"%d\" ticket=\"%S\" postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
954 strcpy(indexPtr,"<chat thread=\"");
955 indexPtr += strlen(indexPtr);
956 sprintf(indexPtr,"%u",self->playerStatus.ms.thread);
957 indexPtr += strlen(indexPtr);
958 strcpy(indexPtr,"\" ticket=\"");
959 indexPtr += strlen(indexPtr);
960 WideToMB(CP_UTF8,self->ticket,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
961 indexPtr += strlen(indexPtr);
962 strcpy(indexPtr,"\" postkey=\"");
963 indexPtr += strlen(indexPtr);
964 strcpy(indexPtr,postKey);
965 indexPtr += strlen(indexPtr);
966 strcpy(indexPtr,"\" user_id=\"");
967 indexPtr += strlen(indexPtr);
968 WideToMB(CP_UTF8,self->playerStatus.user.user_id,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
969 indexPtr += strlen(indexPtr);
970 strcpy(indexPtr,"\" premium=\"");
971 indexPtr += strlen(indexPtr);
972 sprintf(indexPtr,"%u",self->playerStatus.user.is_premium);
973 indexPtr += strlen(indexPtr);
974 strcpy(indexPtr,"\" locale=\"");
975 indexPtr += strlen(indexPtr);
976 WideToMB(CP_UTF8,self->playerStatus.user.userDomain,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
977 indexPtr += strlen(indexPtr);
978 strcpy(indexPtr,"\" vpos=\"");
979 indexPtr += strlen(indexPtr);
983 sprintf(indexPtr,"%u",(self->chatManager.baseVpos + ((timeGetTime() - self->chatManager.commentStartTime) / 10)));
986 indexPtr += strlen(indexPtr);
987 strcpy(indexPtr,"\"");
988 indexPtr += strlen(indexPtr);
990 if(strlen(mailBuf) > 0 && strlen(extendBuf) > 0){
994 strcpy(indexPtr,mailBuf);
995 indexPtr += strlen(indexPtr);
1000 strcpy(indexPtr,extendBuf);
1001 indexPtr += strlen(indexPtr);
1004 } else if(strlen(mailBuf) > 0){
1007 strcpy(indexPtr,mailBuf);
1008 indexPtr += strlen(indexPtr);
1010 } else if(strlen(extendBuf) > 0){
1013 strcpy(indexPtr,extendBuf);
1014 indexPtr += strlen(indexPtr);
1016 strcpy(indexPtr,">");
1017 indexPtr += strlen(indexPtr);
1019 LPTSTR sendBuf = (LPTSTR)&buffer[NICOLIVE_SENDCHATBUFLEN * 4];
1020 LPTSTR sendPtr = sendBuf;
1021 LPCTSTR endPtr= chatbuf + wcslen(chatbuf);
1024 //convertTEXT(indexPtr,chatbuf,indexPtr,endPtr);
1026 for(;(chatbuf) <= (endPtr);(chatbuf)++){
1029 wcscpy((sendBuf),L"&");
1030 (sendBuf) += wcslen(sendBuf);
1033 wcscpy((sendBuf),L"<");
1034 (sendBuf) += wcslen(sendBuf);
1037 wcscpy((sendBuf),L">");
1038 (sendBuf) += wcslen(sendBuf);
1041 wcscpy((sendBuf),L""");
1042 (sendBuf) += wcslen(sendBuf);
1045 wcscpy((sendBuf),L"'");
1046 (sendBuf) += wcslen(sendBuf);
1049 sendBuf[0] = chatbuf[0];
1056 WideToMB(CP_UTF8,sendPtr,indexPtr,NICOLIVE_SENDCHATBUFLEN * 4 - (indexPtr - buffer) - 1);
1057 indexPtr += strlen(indexPtr);
1060 strcpy(indexPtr,"</chat>");
1061 indexPtr[strlen(indexPtr)] = '\0';
1066 INT_PTR sendLen = 0;
1067 INT_PTR sentLen = 0;
1068 INT_PTR max = strlen(buffer) + 1;
1071 sendLen = send(self->chatManager.sock,buffer,max - sentLen,0);
1073 } while(sendLen > 0);
1083 WinHttpCloseHandle(hGetPostKeySession);
1085 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1086 LeaveCriticalSection(&self->sessionManager.cs);
1102 //
\83C
\83\93\83\89\83C
\83\93\8aÖ
\90\94
1107 NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P self,LPCTSTR userSession,HINTERNET hConnect,LPVOID buffer){
1109 NLIB_RESULT rslt = NLIB_ERR_OK;
1114 const UINT_PTR buflen = LENGTH_65536;
1116 LPSTR recvBuffer = (LPSTR)buffer;
1119 DWORD statusCodeSize = sizeof(statusCode);
1124 if(WinHttpSendRequest(hConnect,userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1126 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1131 if(WinHttpReceiveResponse(hConnect,NULL) == FALSE){
1133 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1139 if (WinHttpQueryHeaders(hConnect,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1140 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1145 if (HTTP_STATUS_OK != statusCode){
1146 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1153 if(ReadHttpBody(hConnect,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
1155 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1160 recvBuffer[readSize] = '\0';
1162 recvBuffer = strstr(recvBuffer,"<");
1164 if(recvBuffer == NULL){
1166 rslt = NLIB_ERR_GETPLAYERSTATUS_CHANT_PARSE;
1169 idumpln_mb(CP_UTF8,"playerstatus:%s",recvBuffer);
1172 XMLParse(self,recvBuffer,NPlayerStatus_ElementStartHandler,NPlayerStatus_ElementEndHandler,NPlayerStatus_CharacterDataHandler);
1174 if(rslt != NLIB_ERR_OK){
1191 #define GETNICOLIVEHIS_OBJNAMELENGTH LENGTH_256
1192 #define GETNICOLIVEHIS_COOKIELENGTH LENGTH_512
1194 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect){
1196 NLIB_RESULT rslt = NLIB_ERR_OK;
1198 EnterCriticalSection(&self->sessionManager.cs);
1201 HINTERNET hStreamBrowse = NULL;
1204 TCHAR objectName[GETNICOLIVEHIS_OBJNAMELENGTH] = {L"/watch/"};
1205 TCHAR cookie[GETNICOLIVEHIS_COOKIELENGTH] = {L"Cookie: "};
1207 DWORD statusCodeSize = sizeof(statusCode);
1208 DWORD chunkSize = LENGTH_65536;
1209 LPVOID chunkMemory =self->sessionManager.buffer;
1213 LPTSTR buffer = (LPTSTR)chunkMemory;
1217 if((GETNICOLIVEHIS_OBJNAMELENGTH - wcslen(objectName) <= wcslen(self->playerStatus.stream.id)) || GETNICOLIVEHIS_COOKIELENGTH - wcslen(cookie) <= wcslen(self->userSession)){
1219 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1223 wcscat(objectName,self->playerStatus.stream.id);
1224 wcscat(cookie,self->userSession);
1230 hStreamBrowse = WinHttpOpenRequest(hNicoVideoConnect,L"GET",objectName,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1235 if(WinHttpSendRequest(hStreamBrowse,cookie,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1237 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1242 if(WinHttpReceiveResponse(hStreamBrowse,NULL) == FALSE){
1244 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1249 if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1250 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1255 if (HTTP_STATUS_OK != statusCode){
1256 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1262 if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_SET_COOKIE,WINHTTP_HEADER_NAME_BY_INDEX,buffer,&chunkSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1263 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1268 LPTSTR start =wcsstr(buffer,L"nicolivehistory=");
1270 LPTSTR end = wcsstr(start,L";");
1272 UINT_PTR length = end - start;
1274 if(length >= sizeof(self->nicoLiveHistory)){
1275 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1280 wcsncpy(self->nicoLiveHistory,start,length);
1281 self->nicoLiveHistory[length] = L'\0';
1286 WinHttpCloseHandle(hStreamBrowse);
1289 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1290 LeaveCriticalSection(&self->sessionManager.cs);
1305 #ifdef USE_NLIB_KEEPALIVE
1306 static unsigned int WINAPI NicoLiveKeapALiveThread(void* lpBuffer){
1308 unsigned int rslt = 0;
1310 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1312 rslt = loopCommon(self,self->chatManager.setKeepAliveTimeEvent,self->chatManager.resetEvents[KEEPALLIVERESETEVENT],self->chatManager.onKeepAlliveSend,&self->chatManager.keepAliveTime);
1318 #endif //USE_NLIB_KEEPALIVE
1320 static unsigned int WINAPI NicoLiveHeartBeatThread(void* lpBuffer){
1322 unsigned int rslt = 0;
1324 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1327 rslt = loopCommon(self,self->chatManager.setHeartBeatTimeEvent,self->chatManager.resetEvents[1],self->chatManager.onHeartBeatSend,&self->chatManager.heartBeatTime);
1335 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend,LPDWORD time){
1337 unsigned int rslt = 0;
1338 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1339 WSAEVENT streamEvent[2] = {self->chatManager.endEvent,sendEvent};
1340 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1345 WSASetEvent(resetEvent);
1347 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1350 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1351 if(dwResult == WSA_WAIT_FAILED){
1357 switch(dwResult - WSA_WAIT_EVENT_0){
1364 WSAResetEvent(resetEvent);
1378 WSAResetEvent(sendEvent);
1379 endResult = WSAWaitForMultipleEvents(sizeof(streamEvent) / sizeof(streamEvent[0]),streamEvent,FALSE,*time,FALSE);
1381 if(endResult == WSA_WAIT_TIMEOUT){
1383 nicoLiveOnSend(self);
1384 //dumpln(TEXT("onSend"));
1388 switch(endResult - WSA_WAIT_EVENT_0){
1411 _beginthread(NicoLiveError,0,self);
1416 static VOID OnSendHeartBeat(NicoLiveStream_P self){
1418 if(self->chatManager.heartBeatFlag){
1419 NicoLiveStream_sendHeartBeat(self);
1423 #ifdef USE_NLIB_KEEPALIVE
1424 static VOID OnSendKeepAllive(NicoLiveStream_P self){
1427 if(self->chatManager.keapALiveFlag && self->playerStatus.stream.is_owner == TRUE){
1428 LPCTSTR mail[2] = {L"184",NULL};
1429 NicoLiveStream_sendChat(self,L"/keapalive",mail,NULL);
1436 #define NICOLIVE_RECEVE_CHAT_LENGTH LENGTH_2048
1437 #define NICOLIVE_REQUEST_CHAT_LENGTH LENGTH_256
1438 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer){
1441 unsigned int rslt = 0;
1443 //LPTSTR user_id = NULL;
1444 //LPTSTR name = NULL;
1445 //LPTSTR chatBuf = NULL;
1449 CHAR requestChat[NICOLIVE_REQUEST_CHAT_LENGTH]; //
\91\97\90M
\93d
\95¶
\97p
\83o
\83b
\83t
\83@
1450 LPCSTR sendFormat = "<thread thread=\"%u\" res_from=\"%d\" version=\"20061206\" />"; //
\91\97\90M
\93d
\95¶
\83t
\83H
\81[
\83}
\83b
\83g
1451 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer; //
\83j
\83R
\90¶
\95ú
\91\97\83I
\83u
\83W
\83F
\83N
\83g
1452 INT_PTR sendLen; //
\91\97\90M
\97p
\95¶
\8e\9a\90\94
1453 INT_PTR sentLen; //
\91\97\90M
\8dÏ
\82Ý
\95¶
\8e\9a\90\94
1454 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1455 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1461 WSASetEvent(self->chatManager.resetEvents[0]);
1463 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1466 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1467 if(dwResult == WSA_WAIT_FAILED){
1473 switch(dwResult - WSA_WAIT_EVENT_0){
1480 WSAResetEvent(self->chatManager.resetEvents[0]);
1496 //
\83\
\83P
\83b
\83g
\82Ì
\90Ý
\92è
1497 self->chatManager.sock = GetConectedSocket(self->playerStatus.ms.addr,self->playerStatus.ms.port,SOCK_STREAM,AF_INET,IPPROTO_TCP);
1500 //
\83R
\83\81\83\93\83g
\8eó
\90M
\8aJ
\8en
\82Ì
\89º
\8f\80\94õ
1501 if(self->chatManager.sock == INVALID_SOCKET){
1502 self->error = NLIB_ERR_FAILED_NETWORK;
1511 if(NICOLIVE_REQUEST_CHAT_LENGTH <= _scprintf(sendFormat,self->playerStatus.ms.thread,self->res_from)){
1513 self->error = NLIB_ERR_BUFFER_TOOLITTLE;
1520 sprintf(requestChat,sendFormat,self->playerStatus.ms.thread,self->res_from);
1524 //
\83R
\83\81\83\93\83g
\8eó
\90M
\97v
\8b\81\91\97\90M
\8f\88\97\9d
1528 sendLen = strlen(requestChat) + 1;
1530 len = send(self->chatManager.sock,requestChat,sendLen,0);
1531 if(len == SOCKET_ERROR){
1532 self->error = NLIB_ERR_FAILED_NETWORK;
1540 }while(sentLen < sendLen);
1544 if(NicoLiveRecvChatLoop(self) == FALSE){
1556 _beginthread(NicoLiveError,0,self);
1562 closesocket(self->chatManager.sock);
1577 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self){
1581 //
\83R
\83\81\83\93\83g
\8eó
\90M
\8f\88\97\9d
1583 BOOL rslt = TRUE; //
\8c\8b\89Ê
1584 LPTSTR commentBuf = NULL; //
\83R
\83\81\83\93\83g
\83o
\83b
\83t
\83@
1585 LPTSTR* mailCountBuf = NULL; //
\83\81\81[
\83\8b\83|
\83C
\83\93\83^
\83o
\83b
\83t
\83@
1586 INT_PTR recevedLen; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\92·
1587 INT_PTR messageBufLen; //
\83o
\83b
\83t
\83@
\92·
1591 WSAEVENT hEventArray[2]; //
\8eó
\90M
\81E
\90Ø
\92f
\82ð
\8c\9f\92m
\82·
\82é
\83C
\83x
\83\93\83g
\83I
\83u
\83W
\83F
\83N
\83g
\82Ì
\94z
\97ñ
1592 WSANETWORKEVENTS netEvents; //
\83l
\83b
\83g
\83\8f\81[
\83N
\83C
\83x
\83\93\83g
1593 DWORD dwResult; //
\83C
\83x
\83\93\83g
\82ª
\83E
\83F
\83C
\83g
\8aÖ
\90\94\82Ì
\8c\8b\89Ê
\82ð
\8ai
\94[
\82·
\82é
\95Ï
\90\94
1596 SIZE_T commentBufSize = sizeof(TCHAR) * LENGTH_2048; //
\83R
\83\81\83\93\83g
\83o
\83b
\83t
\83@
\92·
1597 SIZE_T mailCountBufSize = sizeof(LPTSTR) * LENGTH_256; //
\83\81\81[
\83\8b\82Ì
\83|
\83C
\83\93\83^
\97p
\83o
\83b
\83t
\83@
\92·
1600 WSAEVENT hRecvEvent = NULL;
1602 //
\8eó
\90M
\8f\80\94õ
\8f\88\97\9d
1603 self->chatManager.commentCountSum = 0;
1604 hRecvEvent = WSACreateEvent();
1605 self->chatManager.recvBuf[0] = '\0';
1606 WSAEventSelect(self->chatManager.sock, hRecvEvent, FD_READ | FD_CLOSE);
1607 hEventArray[0] = hRecvEvent;
1608 hEventArray[1] = self->chatManager.endEvent;
1610 commentBuf = (LPTSTR)malloc(commentBufSize);
1611 mailCountBuf = (LPTSTR*)malloc(mailCountBufSize);
1613 //
\90Ø
\92f
\82³
\82ê
\82é
\82Ü
\82Å
\83\8b\81[
\83v
1618 //
\91O
\82Ì
\83R
\83\81\83\93\83g
\8eó
\90M
\8e\9e\82É
\97]
\82Á
\82½
\95¶
\8e\9a\97ñ
\82Ì
\92·
\82³
\82ð
\92²
\82×
\82é
1619 messageBufLen = strlen(self->chatManager.recvBuf);
1621 //
\8eó
\90M
\82©
\8fI
\97¹
\83C
\83x
\83\93\83g
\82ð
\8c\9f\92m
\82·
\82é
\82Ü
\82Å
\91Ò
\8b@
1622 dwResult = WSAWaitForMultipleEvents(sizeof(hEventArray) / sizeof(hEventArray[0]),hEventArray,FALSE,WSA_INFINITE,FALSE);
1624 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1625 if(dwResult == WSA_WAIT_FAILED){
1632 //
\83R
\83\81\83\93\83g
\8eó
\90M
\83C
\83x
\83\93\83g
\82ª
\83V
\83O
\83i
\83\8b\82É
\82È
\82Á
\82½
\8fê
\8d\87
1633 if(dwResult - WSA_WAIT_EVENT_0 == 0){
1635 WSAEnumNetworkEvents(self->chatManager.sock,hRecvEvent,&netEvents);
1637 //
\93Ç
\8eæ
\83C
\83x
\83\93\83g
\82Ì
\8fê
\8d\87\83R
\83\81\83\93\83g
\82ð
\8eó
\90M
\82·
\82é
1638 if(netEvents.lNetworkEvents & FD_READ){
1641 recevedLen = recv(self->chatManager.sock,&self->chatManager.recvBuf[messageBufLen],(sizeof(self->chatManager.recvBuf) - 1) - messageBufLen ,0);
1643 if(recevedLen == SOCKET_ERROR){
1644 self->error = NLIB_ERR_FAILED_NETWORK;
1649 self->chatManager.recvBuf[messageBufLen + recevedLen] = '\0';
1656 NicoLiveParseComment(self,commentBuf,messageBufLen + recevedLen,mailCountBuf,&mailCountBufSize,&commentBufSize);
1662 } else if(netEvents.lNetworkEvents && FD_CLOSE){
1666 }//if(netEvents.lNetworkEvents & FD_READ)
1668 } else if(dwResult - WSA_WAIT_EVENT_0 == 1){
1672 }//if(dwResult - WSA_WAIT_EVENT_0 == 0)
1681 self->callBack(NICOLIVE_EVENT_DISCONNECT,self,self->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
1685 WSACloseEvent(hRecvEvent);
1693 static VOID NicoLiveParseComment(NicoLiveStream_P self,LPTSTR commentBuf,UINT_PTR endSize,LPTSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize){
1695 LPTSTR indexPtr; //
\89ð
\90Í
\8e\9e\82Ì
\8ew
\95W
\83|
\83C
\83\93\83^
1696 NicoLiveChat nicoLiveChat; //
\83`
\83\83\83b
\83g
\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1697 NicoLiveThreadComment nicoLiveThreadComment; //
\90Ú
\91±
\89\9e\93\9a\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1698 NicoLiveSendResultComment nicoLiveSendResultComment; //
\91\97\90M
\89\9e\93\9a\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1699 NicoLiveChat nicoLiveChatBase; //
\83`
\83\83\83b
\83g
\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1700 NicoLiveThreadComment nicoLiveThreadCommentBase; //
\90Ú
\91±
\89\9e\93\9a\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1701 NicoLiveSendResultComment nicoLiveSendResultCommentBase;//
\91\97\90M
\89\9e\93\9a\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1702 LPTSTR attrNameStart; //
\91®
\90«
\96¼
\8aJ
\8en
\83|
\83C
\83\93\83^
1703 LPTSTR attrNameEnd; //
\91®
\90«
\96¼
\8fI
\97¹
\83|
\83C
\83\93\83^
1704 LPTSTR attrValueStart; //
\91®
\90«
\92l
\8aJ
\8en
\83|
\83C
\83\93\83^
1705 LPTSTR attrValueEnd; //
\91®
\90«
\92l
\8fI
\97¹
\83|
\83C
\83\93\83^
1706 INT_PTR nameLen; //
\91®
\90«
\82Ì
\96¼
\91O
\82Ì
\92·
\82³
1707 LPTSTR mailIndexPtr; //
\83\81\81[
\83\8b\91®
\90«
\92l
\89ð
\90Í
\97p
\8ew
\95W
\83|
\83C
\83\93\83^
1708 LPTSTR xmlTextPtr; //xml
\83e
\83L
\83X
\83g
\8c`
\8e®
\82Ì
\83f
\81[
\83^
\89ð
\90Í
\8e\9e\82É
\8eg
\97p
\82·
\82é
\83|
\83C
\83\93\83^
1709 LPTSTR xmlTextEnd; //xml
\83e
\83L
\83X
\83g
\8fI
\97¹
\83|
\83C
\83\93\83^
1710 LPTSTR* mailIndex; //
\83\81\81[
\83\8b\83R
\83}
\83\93\83h
\83\8a\83X
\83g
\83|
\83C
\83\93\83^
1711 BOOL isReceveChat = FALSE; //
\83`
\83\83\83b
\83g
\8eó
\90M
\83t
\83\89\83O
1712 SIZE_T commentSizeCh; //
\8eó
\90M
\82µ
\82½
\83R
\83\81\83\93\83g
\82ð
\83\86\83j
\83R
\81[
\83h
\82É
\95Ï
\8a·
\82·
\82é
\82Æ
\82«
\82Ì
\92·
\82³
1713 LPSTR recvBufTmp; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\91\80\8dì
\97p
\83|
\83C
\83\93\83^
1714 LPSTR recvEndPoint; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\8fI
\92[
\83|
\83C
\83\93\83^
1718 recvBufTmp = &self->chatManager.recvBuf[0];
1719 recvEndPoint = &self->chatManager.recvBuf[endSize];
1722 //
\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
\8f\89\8aú
\89»
1723 nicoLiveChatBase.anonymity = L"";
1724 nicoLiveChatBase.chatBuf = L"";
1725 nicoLiveChatBase.date = L"";
1726 nicoLiveChatBase.locale = L"";
1727 nicoLiveChatBase.mail = mailCountBuf;
1728 nicoLiveChatBase.name = L"";
1729 nicoLiveChatBase.no = L"";
1730 nicoLiveChatBase.premium = L"";
1731 nicoLiveChatBase.thread = L"";
1732 nicoLiveChatBase.user_id = L"";
1733 nicoLiveChatBase.vpos = L"";
1734 nicoLiveChatBase.mailCount = 0;
1738 nicoLiveThreadCommentBase.last_res = L"";
1739 nicoLiveThreadCommentBase.thread = L"";
1740 nicoLiveThreadCommentBase.ticket = L"";
1743 nicoLiveSendResultCommentBase.no = L"";
1744 nicoLiveSendResultCommentBase.status = L"";
1745 nicoLiveSendResultCommentBase.thread = L"";
1748 //
\8eó
\90M
\82µ
\82½
\83R
\83\81\83\93\83g
\82ð
\82Ð
\82Æ
\82Â
\82Ìxml
\83m
\81[
\83h
\82²
\82Æ
\82É
\89ð
\90Í
\82·
\82é
1749 for (;recvBufTmp + strlen(recvBufTmp) < recvEndPoint;recvBufTmp += strlen(recvBufTmp) + 1){
1752 commentSizeCh = sizeof(TCHAR) * GetLenToWide(CP_UTF8,recvBufTmp);
1753 extendMalloc(commentBuf,LPTSTR,*commentBufSize,commentSizeCh);
1754 MBToWide(CP_UTF8,recvBufTmp,commentBuf,*commentBufSize);
1756 traceln(TEXT("comment:\r\n%s"),commentBuf);
1757 //thread
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1758 if((indexPtr = wcsstr(commentBuf,L"<thread ")) != NULL){
1760 indexPtr += wcslen(L"<thread ");
1761 skipXMLSPACE(indexPtr);
1766 nicoLiveThreadComment = nicoLiveThreadCommentBase;
1768 while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1769 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1772 nameLen = attrNameEnd - attrNameStart;
1773 if(wcsncmp(attrNameStart,L"ticket",nameLen) == 0){
1776 partString(nicoLiveThreadComment.ticket,attrValueStart,attrValueEnd);
1777 wcscpy(self->ticket,nicoLiveThreadComment.ticket);
1779 } else if(wcsncmp(attrNameStart,L"last_res",nameLen) == 0){
1781 partString(nicoLiveThreadComment.last_res,attrValueStart,attrValueEnd);
1784 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1786 partString(nicoLiveThreadComment.thread,attrValueStart,attrValueEnd);
1787 } else if(wcsncmp(attrNameStart,L"server_time",nameLen) == 0){
1789 NicoLiveStream_setVpos((*self),attrValueStart);
1791 nicoLiveThreadComment.server_time = wcstoul(attrValueStart,NULL,10);
1792 //partString(nicoLiveThreadComment.server_time,attrValueStart,attrValueEnd);
1795 skipXMLSPACE(indexPtr);
1800 self->callBack(NICOLIVE_EVENT_RECEVE_CONNECTRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveThreadComment,self->chatManager.chatNo);
1802 //chat
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1803 } else if((indexPtr = wcsstr(commentBuf,L"<chat ")) != NULL){
1805 indexPtr += wcslen(L"<chat ");
1806 skipXMLSPACE(indexPtr);
1811 nicoLiveChat = nicoLiveChatBase;
1813 while(wcsncmp(indexPtr,L">",wcslen(L">"))){
1815 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1817 nameLen = attrNameEnd - attrNameStart;
1820 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1822 partString(nicoLiveChat.no,attrValueStart,attrValueEnd);
1824 } else if(wcsncmp(attrNameStart,L"date",nameLen) == 0){
1826 NicoLiveStream_setVpos((*self),attrValueStart);
1828 partString(nicoLiveChat.date,attrValueStart,attrValueEnd);
1830 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1832 partString(nicoLiveChat.thread,attrValueStart,attrValueEnd);
1834 } else if(wcsncmp(attrNameStart,L"premium",nameLen) == 0){
1836 partString(nicoLiveChat.premium,attrValueStart,attrValueEnd);
1838 } else if(wcsncmp(attrNameStart,L"anonymity",nameLen) == 0){
1840 partString(nicoLiveChat.anonymity,attrValueStart,attrValueEnd);
1843 } else if(wcsncmp(attrNameStart,L"locale",nameLen) == 0){
1845 partString(nicoLiveChat.locale,attrValueStart,attrValueEnd);
1847 } else if(wcsncmp(attrNameStart,L"vpos",nameLen) == 0){
1849 partString(nicoLiveChat.vpos,attrValueStart,attrValueEnd);
1851 } else if(wcsncmp(attrNameStart,L"user_id",nameLen) == 0){
1853 partString(nicoLiveChat.user_id,attrValueStart,attrValueEnd);
1855 } else if(wcsncmp(attrNameStart,L"name",nameLen) == 0){
1857 partString(nicoLiveChat.name,attrNameStart,attrValueEnd);
1859 } else if(wcsncmp(attrNameStart,L"mail",nameLen) == 0){
1861 nicoLiveChat.mailCount = 1;
1864 for(mailIndexPtr = attrValueStart;mailIndexPtr <= attrValueEnd;mailIndexPtr++){
1866 if(mailIndexPtr[0] == L' '){
1868 nicoLiveChat.mailCount++;
1874 extendMalloc(mailCountBuf,LPTSTR*,*mailCountBufSize,nicoLiveChat.mailCount);
1876 nicoLiveChat.mail = mailCountBuf;
1877 mailCountBuf[0] = NULL;
1879 for(mailIndex = mailCountBuf,mailIndexPtr = attrValueStart,mailIndex[0] = mailIndexPtr;mailIndexPtr < attrValueEnd;mailIndexPtr++){
1882 if(mailIndexPtr[0] == L' '){
1884 mailIndex[0] = mailIndexPtr + 1;
1885 mailIndexPtr[0] = L'\0';
1892 mailIndexPtr[0] = L'\0';
1896 skipXMLSPACE(indexPtr);
1900 xmlTextPtr = indexPtr;
1901 xmlTextEnd = wcsstr(indexPtr,L"<");
1902 convertXMLTEXT(nicoLiveChat.chatBuf,indexPtr,xmlTextPtr,xmlTextEnd);
1906 self->chatManager.chatNo = wcstoul(nicoLiveChat.no,NULL,10);
1910 self->chatManager.commentCountSum++;
1911 isReceveChat = TRUE;
1913 check((_heapchk() == _HEAPOK),TEXT("
\83q
\81[
\83v
\83G
\83\89\81[
\82Å
\82·"));
1915 if((wcscmp(nicoLiveChat.chatBuf,L"/disconnect") == 0 && wcscmp(nicoLiveChat.premium,L"2") == 0)){
1918 _beginthread(NicoLiveSelfDisconnect,0,self);
1920 self->callBack(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&nicoLiveChat,self->chatManager.commentCountSum);
1923 //chat_result
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1924 } else if((indexPtr = wcsstr(commentBuf,L"<chat_result ")) != NULL){
1926 indexPtr += wcslen(L"<chat_result ");
1928 nicoLiveSendResultComment = nicoLiveSendResultCommentBase;
1930 while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1931 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1934 nameLen = attrNameEnd - attrNameStart;
1935 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1938 partString(nicoLiveSendResultComment.no,attrValueStart,attrValueEnd);
1940 } else if(wcsncmp(attrNameStart,L"status",nameLen) == 0){
1942 partString(nicoLiveSendResultComment.status,attrValueStart,attrValueEnd);
1945 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1947 partString(nicoLiveSendResultComment.thread,attrValueStart,attrValueEnd);
1950 skipXMLSPACE(indexPtr);
1953 #ifdef USE_NLIB_KEEPALIVE
1954 //
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\83\8a\83Z
\83b
\83g
1955 WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
1956 #endif //USE_NLIB_KEEPALIVE
1958 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSENDRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveSendResultComment,(NICOLIVE_PARAM)NULL);
1964 if(recvBufTmp == recvEndPoint && isReceveChat){
1965 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSETTLE,self,self->option,self->chatManager.chatNo,self->chatManager.commentCountSum);
1971 strcpy(&self->chatManager.recvBuf[0],recvBufTmp);
1988 static void NicoLiveError(void *buf){
1990 NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1992 nl->callBack(NICOLIVE_EVENT_ERR_CONNECT,nl,nl->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
1994 NicoLiveStream_disConnect(nl);
2002 static void NicoLiveSelfDisconnect(void *buf){
2004 NicoLiveStream_P nl = (NicoLiveStream_P)buf;
2006 dumpln(TEXT("selfdisconnect"),);
2008 NicoLiveStream_disConnect(nl);
2018 static INLINE SOCKET GetConectedSocket(LPCTSTR nordName,LPCTSTR port,int socktype,int addr_famiry,int protocol){
2021 SOCKET rslt = INVALID_SOCKET;
2024 PADDRINFOW res,res0;
2026 ZeroMemory(&hints,sizeof(hints));
2027 hints.ai_socktype = socktype;
2028 hints.ai_family = addr_famiry;
2029 hints.ai_protocol = protocol;
2030 GetAddrInfoW(nordName,port,&hints,&res0);
2033 for(res = res0; res != NULL;res = res->ai_next){
2038 rslt = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
2039 if(rslt == INVALID_SOCKET){
2052 if(connect(rslt,res->ai_addr,(int)res->ai_addrlen) == SOCKET_ERROR){
2067 rslt = INVALID_SOCKET;
2071 //res
\8d\
\91¢
\91Ì
\89ð
\95ú
2081 //
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\8aÖ
\98A
2085 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82ÌID
\82ð
\8eæ
\93¾
2087 NLIB_DECLSPEC LPCTSTR NicoLiveStream_getId(NicoLiveStream_P self){
2089 return self->playerStatus.stream.id;
2094 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83R
\83~
\83\85\83j
\83e
\83B
\94Ô
\8d\86\82ð
\8eæ
\93¾
2096 NLIB_DECLSPEC LPCTSTR NicoLiveStream_getDefaultCommunity(NicoLiveStream_P self){
2098 return self->playerStatus.stream.default_community;
2103 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83v
\83\8d\83o
\83C
\83_
\83^
\83C
\83v
\82ð
\8eæ
\93¾
2105 PROVIDERTYPE NicoLiveStream_getProviderType(NicoLiveStream_P self){
2107 return self->playerStatus.stream.provider_type;
2112 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83I
\81[
\83i
\81[
\83t
\83\89\83O
\82ð
\8eæ
\93¾
2114 BOOL NicoLiveStream_isOwner(NicoLiveStream_P self){
2116 return self->playerStatus.stream.is_owner;
2120 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\8aJ
\8en
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2122 time_t NicoLiveStream_getStartTime(NicoLiveStream_P self){
2124 return self->playerStatus.stream.start_time;
2128 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\8fI
\97¹
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2130 time_t NicoLiveStream_getEndTime(NicoLiveStream_P self){
2132 return self->playerStatus.stream.end_time;
2136 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\8aJ
\8fê
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2138 time_t NicoLiveStream_getOpenTime(NicoLiveStream_P self){
2140 return self->playerStatus.stream.open_time;
2145 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83x
\81[
\83X
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2147 time_t NicoLiveStream_getBaseTime(NicoLiveStream_P self){
2149 return self->playerStatus.stream.base_time;
2154 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83^
\83C
\83g
\83\8b\8eæ
\93¾
2156 LPCTSTR NicoLiveStream_getTitle(NicoLiveStream_P self){
2157 #ifdef PLAYERSTATUS_GET_TITLE
2158 return self->playerStatus.stream.title;
2160 static const LPCTSTR rslt = TEXT("");
2165 BOOL NicoLiveStream_isPremium(NicoLiveStream_P self){
2167 return self->playerStatus.user.is_premium;