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 while(WSAResetEvent(self->chatManager.startEvent) == FALSE);
696 while(WSASetEvent(self->chatManager.endEvent)== FALSE);
702 WSAWaitForMultipleEvents(sizeof(self->chatManager.resetEvents) / sizeof(self->chatManager.resetEvents[0]),self->chatManager.resetEvents,TRUE,WSA_INFINITE,FALSE);
706 //nicoLiveStream_Initialize(*self);
707 ZeroMemory(&self->playerStatus,sizeof(self->playerStatus));
708 WSAResetEvent(self->chatManager.endEvent);
710 WinHttpCloseHandle(self->sessionManager.getPlayerStatusSession);
711 self->sessionManager.getPlayerStatusSession = NULL;
712 WinHttpCloseHandle(self->sessionManager.heartBeatSession);
713 self->sessionManager.heartBeatSession = NULL;
717 self->isConnecting = FALSE;
730 #define NICOLIVE_SENDCHATBUFLEN LENGTH_4096
731 #define NICOLIVE_SENDFORMAT "<chat thread=\"%d\" ticket=\"%S\" postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
733 NLIB_RESULT NicoLiveStream_sendChat(NicoLiveStream_P self,LPCTSTR chatbuf,LPCTSTR *mail,LPCTSTR *extends){
735 NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
736 EnterCriticalSection(&self->sessionManager.cs);
739 const UINT_PTR buflen = LENGTH_65536 * 4;
740 LPVOID chunk = self->sessionManager.buffer;
743 LPSTR postKeyBuf = (LPSTR)chunk;
744 LPTSTR postKeyReqBuf = (LPTSTR)&postKeyBuf[NICOLIVE_SENDCHATBUFLEN];
745 LPTSTR cookieBuf = &postKeyReqBuf[NICOLIVE_SENDCHATBUFLEN];
747 DWORD statusCodeSize = sizeof(statusCode);
750 //HINTERNET hWatchLiveNicoVideo = NULL;
751 HINTERNET hGetPostKeySession = NULL;
754 if(self->isConnecting == FALSE){
755 rslt = NLIB_ERR_NOT_LIVECONNECT;
758 if(chatbuf == NULL || wcslen(chatbuf) >= LENGTH_1024){
760 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
767 _swprintf(postKeyReqBuf,L"api/getpostkey?thread=%u&block_no=%u",self->playerStatus.ms.thread,self->chatManager.chatNo / 100);
769 //hWatchLiveNicoVideo = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
770 hGetPostKeySession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",postKeyReqBuf,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
773 //_swprintf(cookieBuf,L"Cookie: %s; %s",self->userSession,self->nicoLiveHistory);
774 _swprintf(cookieBuf,L"Cookie: %s",self->userSession);
776 if(WinHttpSendRequest(hGetPostKeySession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
778 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
784 if(WinHttpReceiveResponse(hGetPostKeySession,NULL) == FALSE){
786 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
792 if (WinHttpQueryHeaders(hGetPostKeySession,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
793 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
798 if (HTTP_STATUS_OK != statusCode){
799 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
807 if(ReadHttpBody(hGetPostKeySession,(LPBYTE)postKeyBuf,buflen,&readSize) == FALSE){
809 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
813 postKeyBuf[readSize] = '\0';
814 postKey = strstr(postKeyBuf,"=") + 1;
818 LPSTR buffer = (LPSTR)&cookieBuf[NICOLIVE_SENDCHATBUFLEN];
823 //mail
\83R
\83}
\83\93\83h
\8dì
\90¬
824 if(mail == NULL || mail[0] == NULL){
830 mailBuf = (LPSTR)postKeyReqBuf;
832 strcpy(indexPtr,"mail=\"");
833 indexPtr += strlen(indexPtr);
835 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
836 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
837 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
843 WideToMB(CP_UTF8,mail[0],indexPtr,len);
844 indexPtr += strlen(indexPtr);
847 for(mail++;mail[0] != NULL;mail++){
852 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
854 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
855 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
860 WideToMB(CP_UTF8,mail[0],indexPtr,len);
861 indexPtr += strlen(indexPtr);
865 strcpy(indexPtr,"\"");
872 //
\8ag
\92£
\91®
\90«
\8dì
\90¬
873 if(extends == NULL || extends[0] == NULL){
879 extendBuf =(LPSTR)cookieBuf;
880 indexPtr = extendBuf;
883 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
885 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
886 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
890 WideToMB(CP_UTF8,extends[0],indexPtr,len);
892 indexPtr += strlen(indexPtr);
894 strcpy(indexPtr,"=\"");
895 indexPtr += strlen(indexPtr);
898 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
900 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
901 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
905 WideToMB(CP_UTF8,extends[1],indexPtr,len);
908 for(extends+= 2;extends[0] != NULL;extends+=2){
913 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
915 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
916 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
920 WideToMB(CP_UTF8,extends[0],indexPtr,len);
922 indexPtr += strlen(indexPtr);
928 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
930 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
931 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
935 WideToMB(CP_UTF8,extends[1],indexPtr,len);
940 indexPtr += strlen(indexPtr);
941 strcpy(indexPtr,"\"");
947 //
\83`
\83\83\83b
\83g
\91\97\90M
\83R
\83\81\83\93\83g
\8dì
\90¬
950 //
\96{
\93\96\82Í
\82±
\82¤
\82µ
\82½
\82¢:"<chat thread=\"%d\" ticket=\"%S\" postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
951 strcpy(indexPtr,"<chat thread=\"");
952 indexPtr += strlen(indexPtr);
953 sprintf(indexPtr,"%u",self->playerStatus.ms.thread);
954 indexPtr += strlen(indexPtr);
955 strcpy(indexPtr,"\" ticket=\"");
956 indexPtr += strlen(indexPtr);
957 WideToMB(CP_UTF8,self->ticket,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
958 indexPtr += strlen(indexPtr);
959 strcpy(indexPtr,"\" postkey=\"");
960 indexPtr += strlen(indexPtr);
961 strcpy(indexPtr,postKey);
962 indexPtr += strlen(indexPtr);
963 strcpy(indexPtr,"\" user_id=\"");
964 indexPtr += strlen(indexPtr);
965 WideToMB(CP_UTF8,self->playerStatus.user.user_id,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
966 indexPtr += strlen(indexPtr);
967 strcpy(indexPtr,"\" premium=\"");
968 indexPtr += strlen(indexPtr);
969 sprintf(indexPtr,"%u",self->playerStatus.user.is_premium);
970 indexPtr += strlen(indexPtr);
971 strcpy(indexPtr,"\" locale=\"");
972 indexPtr += strlen(indexPtr);
973 WideToMB(CP_UTF8,self->playerStatus.user.userDomain,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
974 indexPtr += strlen(indexPtr);
975 strcpy(indexPtr,"\" vpos=\"");
976 indexPtr += strlen(indexPtr);
980 sprintf(indexPtr,"%u",(self->chatManager.baseVpos + ((timeGetTime() - self->chatManager.commentStartTime) / 10)));
983 indexPtr += strlen(indexPtr);
984 strcpy(indexPtr,"\"");
985 indexPtr += strlen(indexPtr);
987 if(strlen(mailBuf) > 0 && strlen(extendBuf) > 0){
991 strcpy(indexPtr,mailBuf);
992 indexPtr += strlen(indexPtr);
997 strcpy(indexPtr,extendBuf);
998 indexPtr += strlen(indexPtr);
1001 } else if(strlen(mailBuf) > 0){
1004 strcpy(indexPtr,mailBuf);
1005 indexPtr += strlen(indexPtr);
1007 } else if(strlen(extendBuf) > 0){
1010 strcpy(indexPtr,extendBuf);
1011 indexPtr += strlen(indexPtr);
1013 strcpy(indexPtr,">");
1014 indexPtr += strlen(indexPtr);
1016 LPTSTR sendBuf = (LPTSTR)&buffer[NICOLIVE_SENDCHATBUFLEN * 4];
1017 LPTSTR sendPtr = sendBuf;
1018 LPCTSTR endPtr= chatbuf + wcslen(chatbuf);
1021 //convertTEXT(indexPtr,chatbuf,indexPtr,endPtr);
1023 for(;(chatbuf) <= (endPtr);(chatbuf)++){
1026 wcscpy((sendBuf),L"&");
1027 (sendBuf) += wcslen(sendBuf);
1030 wcscpy((sendBuf),L"<");
1031 (sendBuf) += wcslen(sendBuf);
1034 wcscpy((sendBuf),L">");
1035 (sendBuf) += wcslen(sendBuf);
1038 wcscpy((sendBuf),L""");
1039 (sendBuf) += wcslen(sendBuf);
1042 wcscpy((sendBuf),L"'");
1043 (sendBuf) += wcslen(sendBuf);
1046 sendBuf[0] = chatbuf[0];
1053 WideToMB(CP_UTF8,sendPtr,indexPtr,NICOLIVE_SENDCHATBUFLEN * 4 - (indexPtr - buffer) - 1);
1054 indexPtr += strlen(indexPtr);
1057 strcpy(indexPtr,"</chat>");
1058 indexPtr[strlen(indexPtr)] = '\0';
1063 INT_PTR sendLen = 0;
1064 INT_PTR sentLen = 0;
1065 INT_PTR max = strlen(buffer) + 1;
1068 sendLen = send(self->chatManager.sock,buffer,max - sentLen,0);
1070 } while(sendLen > 0);
1080 WinHttpCloseHandle(hGetPostKeySession);
1082 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1083 LeaveCriticalSection(&self->sessionManager.cs);
1099 //
\83C
\83\93\83\89\83C
\83\93\8aÖ
\90\94
1104 NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P self,LPCTSTR userSession,HINTERNET hConnect,LPVOID buffer){
1106 NLIB_RESULT rslt = NLIB_ERR_OK;
1111 const UINT_PTR buflen = LENGTH_65536;
1113 LPSTR recvBuffer = (LPSTR)buffer;
1116 DWORD statusCodeSize = sizeof(statusCode);
1121 if(WinHttpSendRequest(hConnect,userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1123 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1128 if(WinHttpReceiveResponse(hConnect,NULL) == FALSE){
1130 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1136 if (WinHttpQueryHeaders(hConnect,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1137 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1142 if (HTTP_STATUS_OK != statusCode){
1143 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1150 if(ReadHttpBody(hConnect,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
1152 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1157 recvBuffer[readSize] = '\0';
1159 recvBuffer = strstr(recvBuffer,"<");
1161 if(recvBuffer == NULL){
1163 rslt = NLIB_ERR_GETPLAYERSTATUS_CHANT_PARSE;
1166 idumpln_mb(CP_UTF8,"playerstatus:%s",recvBuffer);
1169 XMLParse(self,recvBuffer,NPlayerStatus_ElementStartHandler,NPlayerStatus_ElementEndHandler,NPlayerStatus_CharacterDataHandler);
1171 if(rslt != NLIB_ERR_OK){
1188 #define GETNICOLIVEHIS_OBJNAMELENGTH LENGTH_256
1189 #define GETNICOLIVEHIS_COOKIELENGTH LENGTH_512
1191 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect){
1193 NLIB_RESULT rslt = NLIB_ERR_OK;
1195 EnterCriticalSection(&self->sessionManager.cs);
1198 HINTERNET hStreamBrowse = NULL;
1201 TCHAR objectName[GETNICOLIVEHIS_OBJNAMELENGTH] = {L"/watch/"};
1202 TCHAR cookie[GETNICOLIVEHIS_COOKIELENGTH] = {L"Cookie: "};
1204 DWORD statusCodeSize = sizeof(statusCode);
1205 DWORD chunkSize = LENGTH_65536;
1206 LPVOID chunkMemory =self->sessionManager.buffer;
1210 LPTSTR buffer = (LPTSTR)chunkMemory;
1214 if((GETNICOLIVEHIS_OBJNAMELENGTH - wcslen(objectName) <= wcslen(self->playerStatus.stream.id)) || GETNICOLIVEHIS_COOKIELENGTH - wcslen(cookie) <= wcslen(self->userSession)){
1216 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1220 wcscat(objectName,self->playerStatus.stream.id);
1221 wcscat(cookie,self->userSession);
1227 hStreamBrowse = WinHttpOpenRequest(hNicoVideoConnect,L"GET",objectName,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1232 if(WinHttpSendRequest(hStreamBrowse,cookie,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1234 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1239 if(WinHttpReceiveResponse(hStreamBrowse,NULL) == FALSE){
1241 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1246 if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1247 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1252 if (HTTP_STATUS_OK != statusCode){
1253 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1259 if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_SET_COOKIE,WINHTTP_HEADER_NAME_BY_INDEX,buffer,&chunkSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1260 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1265 LPTSTR start =wcsstr(buffer,L"nicolivehistory=");
1267 LPTSTR end = wcsstr(start,L";");
1269 UINT_PTR length = end - start;
1271 if(length >= sizeof(self->nicoLiveHistory)){
1272 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1277 wcsncpy(self->nicoLiveHistory,start,length);
1278 self->nicoLiveHistory[length] = L'\0';
1283 WinHttpCloseHandle(hStreamBrowse);
1286 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1287 LeaveCriticalSection(&self->sessionManager.cs);
1302 #ifdef USE_NLIB_KEEPALIVE
1303 static unsigned int WINAPI NicoLiveKeapALiveThread(void* lpBuffer){
1305 unsigned int rslt = 0;
1307 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1309 rslt = loopCommon(self,self->chatManager.setKeepAliveTimeEvent,self->chatManager.resetEvents[KEEPALLIVERESETEVENT],self->chatManager.onKeepAlliveSend,&self->chatManager.keepAliveTime);
1315 #endif //USE_NLIB_KEEPALIVE
1317 static unsigned int WINAPI NicoLiveHeartBeatThread(void* lpBuffer){
1319 unsigned int rslt = 0;
1321 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1324 rslt = loopCommon(self,self->chatManager.setHeartBeatTimeEvent,self->chatManager.resetEvents[1],self->chatManager.onHeartBeatSend,&self->chatManager.heartBeatTime);
1332 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend,LPDWORD time){
1334 unsigned int rslt = 0;
1335 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1336 WSAEVENT streamEvent[2] = {self->chatManager.endEvent,sendEvent};
1337 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1342 WSASetEvent(resetEvent);
1344 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1347 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1348 if(dwResult == WSA_WAIT_FAILED){
1354 switch(dwResult - WSA_WAIT_EVENT_0){
1361 WSAResetEvent(resetEvent);
1375 WSAResetEvent(sendEvent);
1376 endResult = WSAWaitForMultipleEvents(sizeof(streamEvent) / sizeof(streamEvent[0]),streamEvent,FALSE,*time,FALSE);
1378 if(endResult == WSA_WAIT_TIMEOUT){
1380 nicoLiveOnSend(self);
1381 //dumpln(TEXT("onSend"));
1385 switch(endResult - WSA_WAIT_EVENT_0){
1408 _beginthread(NicoLiveError,0,self);
1413 static VOID OnSendHeartBeat(NicoLiveStream_P self){
1415 if(self->chatManager.heartBeatFlag){
1416 NicoLiveStream_sendHeartBeat(self);
1420 #ifdef USE_NLIB_KEEPALIVE
1421 static VOID OnSendKeepAllive(NicoLiveStream_P self){
1424 if(self->chatManager.keapALiveFlag && self->playerStatus.stream.is_owner == TRUE){
1425 LPCTSTR mail[2] = {L"184",NULL};
1426 NicoLiveStream_sendChat(self,L"/keapalive",mail,NULL);
1433 #define NICOLIVE_RECEVE_CHAT_LENGTH LENGTH_2048
1434 #define NICOLIVE_REQUEST_CHAT_LENGTH LENGTH_256
1435 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer){
1438 unsigned int rslt = 0;
1440 //LPTSTR user_id = NULL;
1441 //LPTSTR name = NULL;
1442 //LPTSTR chatBuf = NULL;
1446 CHAR requestChat[NICOLIVE_REQUEST_CHAT_LENGTH]; //
\91\97\90M
\93d
\95¶
\97p
\83o
\83b
\83t
\83@
1447 LPCSTR sendFormat = "<thread thread=\"%u\" res_from=\"%d\" version=\"20061206\" />"; //
\91\97\90M
\93d
\95¶
\83t
\83H
\81[
\83}
\83b
\83g
1448 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer; //
\83j
\83R
\90¶
\95ú
\91\97\83I
\83u
\83W
\83F
\83N
\83g
1449 INT_PTR sendLen; //
\91\97\90M
\97p
\95¶
\8e\9a\90\94
1450 INT_PTR sentLen; //
\91\97\90M
\8dÏ
\82Ý
\95¶
\8e\9a\90\94
1451 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1452 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1458 WSASetEvent(self->chatManager.resetEvents[0]);
1460 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1463 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1464 if(dwResult == WSA_WAIT_FAILED){
1470 switch(dwResult - WSA_WAIT_EVENT_0){
1477 WSAResetEvent(self->chatManager.resetEvents[0]);
1493 //
\83\
\83P
\83b
\83g
\82Ì
\90Ý
\92è
1494 self->chatManager.sock = GetConectedSocket(self->playerStatus.ms.addr,self->playerStatus.ms.port,SOCK_STREAM,AF_INET,IPPROTO_TCP);
1497 //
\83R
\83\81\83\93\83g
\8eó
\90M
\8aJ
\8en
\82Ì
\89º
\8f\80\94õ
1498 if(self->chatManager.sock == INVALID_SOCKET){
1499 self->error = NLIB_ERR_FAILED_NETWORK;
1508 if(NICOLIVE_REQUEST_CHAT_LENGTH <= _scprintf(sendFormat,self->playerStatus.ms.thread,self->res_from)){
1510 self->error = NLIB_ERR_BUFFER_TOOLITTLE;
1517 sprintf(requestChat,sendFormat,self->playerStatus.ms.thread,self->res_from);
1521 //
\83R
\83\81\83\93\83g
\8eó
\90M
\97v
\8b\81\91\97\90M
\8f\88\97\9d
1525 sendLen = strlen(requestChat) + 1;
1527 len = send(self->chatManager.sock,requestChat,sendLen,0);
1528 if(len == SOCKET_ERROR){
1529 self->error = NLIB_ERR_FAILED_NETWORK;
1537 }while(sentLen < sendLen);
1541 if(NicoLiveRecvChatLoop(self) == FALSE){
1553 _beginthread(NicoLiveError,0,self);
1559 closesocket(self->chatManager.sock);
1574 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self){
1578 //
\83R
\83\81\83\93\83g
\8eó
\90M
\8f\88\97\9d
1580 BOOL rslt = TRUE; //
\8c\8b\89Ê
1581 LPTSTR commentBuf = NULL; //
\83R
\83\81\83\93\83g
\83o
\83b
\83t
\83@
1582 LPTSTR* mailCountBuf = NULL; //
\83\81\81[
\83\8b\83|
\83C
\83\93\83^
\83o
\83b
\83t
\83@
1583 INT_PTR recevedLen; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\92·
1584 INT_PTR messageBufLen; //
\83o
\83b
\83t
\83@
\92·
1588 WSAEVENT hEventArray[2]; //
\8eó
\90M
\81E
\90Ø
\92f
\82ð
\8c\9f\92m
\82·
\82é
\83C
\83x
\83\93\83g
\83I
\83u
\83W
\83F
\83N
\83g
\82Ì
\94z
\97ñ
1589 WSANETWORKEVENTS netEvents; //
\83l
\83b
\83g
\83\8f\81[
\83N
\83C
\83x
\83\93\83g
1590 DWORD dwResult; //
\83C
\83x
\83\93\83g
\82ª
\83E
\83F
\83C
\83g
\8aÖ
\90\94\82Ì
\8c\8b\89Ê
\82ð
\8ai
\94[
\82·
\82é
\95Ï
\90\94
1593 SIZE_T commentBufSize = sizeof(TCHAR) * LENGTH_2048; //
\83R
\83\81\83\93\83g
\83o
\83b
\83t
\83@
\92·
1594 SIZE_T mailCountBufSize = sizeof(LPTSTR) * LENGTH_256; //
\83\81\81[
\83\8b\82Ì
\83|
\83C
\83\93\83^
\97p
\83o
\83b
\83t
\83@
\92·
1597 WSAEVENT hRecvEvent = NULL;
1599 //
\8eó
\90M
\8f\80\94õ
\8f\88\97\9d
1600 self->chatManager.commentCountSum = 0;
1601 hRecvEvent = WSACreateEvent();
1602 self->chatManager.recvBuf[0] = '\0';
1603 WSAEventSelect(self->chatManager.sock, hRecvEvent, FD_READ | FD_CLOSE);
1604 hEventArray[0] = hRecvEvent;
1605 hEventArray[1] = self->chatManager.endEvent;
1607 commentBuf = (LPTSTR)malloc(commentBufSize);
1608 mailCountBuf = (LPTSTR*)malloc(mailCountBufSize);
1610 //
\90Ø
\92f
\82³
\82ê
\82é
\82Ü
\82Å
\83\8b\81[
\83v
1615 //
\91O
\82Ì
\83R
\83\81\83\93\83g
\8eó
\90M
\8e\9e\82É
\97]
\82Á
\82½
\95¶
\8e\9a\97ñ
\82Ì
\92·
\82³
\82ð
\92²
\82×
\82é
1616 messageBufLen = strlen(self->chatManager.recvBuf);
1618 //
\8eó
\90M
\82©
\8fI
\97¹
\83C
\83x
\83\93\83g
\82ð
\8c\9f\92m
\82·
\82é
\82Ü
\82Å
\91Ò
\8b@
1619 dwResult = WSAWaitForMultipleEvents(sizeof(hEventArray) / sizeof(hEventArray[0]),hEventArray,FALSE,WSA_INFINITE,FALSE);
1621 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1622 if(dwResult == WSA_WAIT_FAILED){
1629 //
\83R
\83\81\83\93\83g
\8eó
\90M
\83C
\83x
\83\93\83g
\82ª
\83V
\83O
\83i
\83\8b\82É
\82È
\82Á
\82½
\8fê
\8d\87
1630 if(dwResult - WSA_WAIT_EVENT_0 == 0){
1632 WSAEnumNetworkEvents(self->chatManager.sock,hRecvEvent,&netEvents);
1634 //
\93Ç
\8eæ
\83C
\83x
\83\93\83g
\82Ì
\8fê
\8d\87\83R
\83\81\83\93\83g
\82ð
\8eó
\90M
\82·
\82é
1635 if(netEvents.lNetworkEvents & FD_READ){
1638 recevedLen = recv(self->chatManager.sock,&self->chatManager.recvBuf[messageBufLen],(sizeof(self->chatManager.recvBuf) - 1) - messageBufLen ,0);
1640 if(recevedLen == SOCKET_ERROR){
1641 self->error = NLIB_ERR_FAILED_NETWORK;
1646 self->chatManager.recvBuf[messageBufLen + recevedLen] = '\0';
1653 NicoLiveParseComment(self,commentBuf,messageBufLen + recevedLen,mailCountBuf,&mailCountBufSize,&commentBufSize);
1659 } else if(netEvents.lNetworkEvents && FD_CLOSE){
1663 }//if(netEvents.lNetworkEvents & FD_READ)
1665 } else if(dwResult - WSA_WAIT_EVENT_0 == 1){
1669 }//if(dwResult - WSA_WAIT_EVENT_0 == 0)
1678 self->callBack(NICOLIVE_EVENT_DISCONNECT,self,self->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
1682 WSACloseEvent(hRecvEvent);
1690 static VOID NicoLiveParseComment(NicoLiveStream_P self,LPTSTR commentBuf,UINT_PTR endSize,LPTSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize){
1692 LPTSTR indexPtr; //
\89ð
\90Í
\8e\9e\82Ì
\8ew
\95W
\83|
\83C
\83\93\83^
1693 NicoLiveChat nicoLiveChat; //
\83`
\83\83\83b
\83g
\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1694 NicoLiveThreadComment nicoLiveThreadComment; //
\90Ú
\91±
\89\9e\93\9a\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1695 NicoLiveSendResultComment nicoLiveSendResultComment; //
\91\97\90M
\89\9e\93\9a\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1696 NicoLiveChat nicoLiveChatBase; //
\83`
\83\83\83b
\83g
\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1697 NicoLiveThreadComment nicoLiveThreadCommentBase; //
\90Ú
\91±
\89\9e\93\9a\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1698 NicoLiveSendResultComment nicoLiveSendResultCommentBase;//
\91\97\90M
\89\9e\93\9a\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1699 LPTSTR attrNameStart; //
\91®
\90«
\96¼
\8aJ
\8en
\83|
\83C
\83\93\83^
1700 LPTSTR attrNameEnd; //
\91®
\90«
\96¼
\8fI
\97¹
\83|
\83C
\83\93\83^
1701 LPTSTR attrValueStart; //
\91®
\90«
\92l
\8aJ
\8en
\83|
\83C
\83\93\83^
1702 LPTSTR attrValueEnd; //
\91®
\90«
\92l
\8fI
\97¹
\83|
\83C
\83\93\83^
1703 INT_PTR nameLen; //
\91®
\90«
\82Ì
\96¼
\91O
\82Ì
\92·
\82³
1704 LPTSTR mailIndexPtr; //
\83\81\81[
\83\8b\91®
\90«
\92l
\89ð
\90Í
\97p
\8ew
\95W
\83|
\83C
\83\93\83^
1705 LPTSTR xmlTextPtr; //xml
\83e
\83L
\83X
\83g
\8c`
\8e®
\82Ì
\83f
\81[
\83^
\89ð
\90Í
\8e\9e\82É
\8eg
\97p
\82·
\82é
\83|
\83C
\83\93\83^
1706 LPTSTR xmlTextEnd; //xml
\83e
\83L
\83X
\83g
\8fI
\97¹
\83|
\83C
\83\93\83^
1707 LPTSTR* mailIndex; //
\83\81\81[
\83\8b\83R
\83}
\83\93\83h
\83\8a\83X
\83g
\83|
\83C
\83\93\83^
1708 BOOL isReceveChat = FALSE; //
\83`
\83\83\83b
\83g
\8eó
\90M
\83t
\83\89\83O
1709 SIZE_T commentSizeCh; //
\8eó
\90M
\82µ
\82½
\83R
\83\81\83\93\83g
\82ð
\83\86\83j
\83R
\81[
\83h
\82É
\95Ï
\8a·
\82·
\82é
\82Æ
\82«
\82Ì
\92·
\82³
1710 LPSTR recvBufTmp; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\91\80\8dì
\97p
\83|
\83C
\83\93\83^
1711 LPSTR recvEndPoint; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\8fI
\92[
\83|
\83C
\83\93\83^
1715 recvBufTmp = &self->chatManager.recvBuf[0];
1716 recvEndPoint = &self->chatManager.recvBuf[endSize];
1719 //
\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
\8f\89\8aú
\89»
1720 nicoLiveChatBase.anonymity = L"";
1721 nicoLiveChatBase.chatBuf = L"";
1722 nicoLiveChatBase.date = L"";
1723 nicoLiveChatBase.locale = L"";
1724 nicoLiveChatBase.mail = mailCountBuf;
1725 nicoLiveChatBase.name = L"";
1726 nicoLiveChatBase.no = L"";
1727 nicoLiveChatBase.premium = L"";
1728 nicoLiveChatBase.thread = L"";
1729 nicoLiveChatBase.user_id = L"";
1730 nicoLiveChatBase.vpos = L"";
1731 nicoLiveChatBase.mailCount = 0;
1735 nicoLiveThreadCommentBase.last_res = L"";
1736 nicoLiveThreadCommentBase.thread = L"";
1737 nicoLiveThreadCommentBase.ticket = L"";
1740 nicoLiveSendResultCommentBase.no = L"";
1741 nicoLiveSendResultCommentBase.status = L"";
1742 nicoLiveSendResultCommentBase.thread = L"";
1745 //
\8eó
\90M
\82µ
\82½
\83R
\83\81\83\93\83g
\82ð
\82Ð
\82Æ
\82Â
\82Ìxml
\83m
\81[
\83h
\82²
\82Æ
\82É
\89ð
\90Í
\82·
\82é
1746 for (;recvBufTmp + strlen(recvBufTmp) < recvEndPoint;recvBufTmp += strlen(recvBufTmp) + 1){
1749 commentSizeCh = sizeof(TCHAR) * GetLenToWide(CP_UTF8,recvBufTmp);
1750 extendMalloc(commentBuf,LPTSTR,*commentBufSize,commentSizeCh);
1751 MBToWide(CP_UTF8,recvBufTmp,commentBuf,*commentBufSize);
1753 traceln(TEXT("comment:\r\n%s"),commentBuf);
1754 //thread
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1755 if((indexPtr = wcsstr(commentBuf,L"<thread ")) != NULL){
1757 indexPtr += wcslen(L"<thread ");
1758 skipXMLSPACE(indexPtr);
1763 nicoLiveThreadComment = nicoLiveThreadCommentBase;
1765 while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1766 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1769 nameLen = attrNameEnd - attrNameStart;
1770 if(wcsncmp(attrNameStart,L"ticket",nameLen) == 0){
1773 partString(nicoLiveThreadComment.ticket,attrValueStart,attrValueEnd);
1774 wcscpy(self->ticket,nicoLiveThreadComment.ticket);
1776 } else if(wcsncmp(attrNameStart,L"last_res",nameLen) == 0){
1778 partString(nicoLiveThreadComment.last_res,attrValueStart,attrValueEnd);
1781 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1783 partString(nicoLiveThreadComment.thread,attrValueStart,attrValueEnd);
1784 } else if(wcsncmp(attrNameStart,L"server_time",nameLen) == 0){
1786 NicoLiveStream_setVpos((*self),attrValueStart);
1788 nicoLiveThreadComment.server_time = wcstoul(attrValueStart,NULL,10);
1789 //partString(nicoLiveThreadComment.server_time,attrValueStart,attrValueEnd);
1792 skipXMLSPACE(indexPtr);
1797 self->callBack(NICOLIVE_EVENT_RECEVE_CONNECTRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveThreadComment,self->chatManager.chatNo);
1799 //chat
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1800 } else if((indexPtr = wcsstr(commentBuf,L"<chat ")) != NULL){
1802 indexPtr += wcslen(L"<chat ");
1803 skipXMLSPACE(indexPtr);
1808 nicoLiveChat = nicoLiveChatBase;
1810 while(wcsncmp(indexPtr,L">",wcslen(L">"))){
1812 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1814 nameLen = attrNameEnd - attrNameStart;
1817 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1819 partString(nicoLiveChat.no,attrValueStart,attrValueEnd);
1821 } else if(wcsncmp(attrNameStart,L"date",nameLen) == 0){
1823 NicoLiveStream_setVpos((*self),attrValueStart);
1825 partString(nicoLiveChat.date,attrValueStart,attrValueEnd);
1827 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1829 partString(nicoLiveChat.thread,attrValueStart,attrValueEnd);
1831 } else if(wcsncmp(attrNameStart,L"premium",nameLen) == 0){
1833 partString(nicoLiveChat.premium,attrValueStart,attrValueEnd);
1835 } else if(wcsncmp(attrNameStart,L"anonymity",nameLen) == 0){
1837 partString(nicoLiveChat.anonymity,attrValueStart,attrValueEnd);
1840 } else if(wcsncmp(attrNameStart,L"locale",nameLen) == 0){
1842 partString(nicoLiveChat.locale,attrValueStart,attrValueEnd);
1844 } else if(wcsncmp(attrNameStart,L"vpos",nameLen) == 0){
1846 partString(nicoLiveChat.vpos,attrValueStart,attrValueEnd);
1848 } else if(wcsncmp(attrNameStart,L"user_id",nameLen) == 0){
1850 partString(nicoLiveChat.user_id,attrValueStart,attrValueEnd);
1852 } else if(wcsncmp(attrNameStart,L"name",nameLen) == 0){
1854 partString(nicoLiveChat.name,attrNameStart,attrValueEnd);
1856 } else if(wcsncmp(attrNameStart,L"mail",nameLen) == 0){
1858 nicoLiveChat.mailCount = 1;
1861 for(mailIndexPtr = attrValueStart;mailIndexPtr <= attrValueEnd;mailIndexPtr++){
1863 if(mailIndexPtr[0] == L' '){
1865 nicoLiveChat.mailCount++;
1871 extendMalloc(mailCountBuf,LPTSTR*,*mailCountBufSize,nicoLiveChat.mailCount);
1873 nicoLiveChat.mail = mailCountBuf;
1874 mailCountBuf[0] = NULL;
1876 for(mailIndex = mailCountBuf,mailIndexPtr = attrValueStart,mailIndex[0] = mailIndexPtr;mailIndexPtr < attrValueEnd;mailIndexPtr++){
1879 if(mailIndexPtr[0] == L' '){
1881 mailIndex[0] = mailIndexPtr + 1;
1882 mailIndexPtr[0] = L'\0';
1889 mailIndexPtr[0] = L'\0';
1893 skipXMLSPACE(indexPtr);
1897 xmlTextPtr = indexPtr;
1898 xmlTextEnd = wcsstr(indexPtr,L"<");
1899 convertXMLTEXT(nicoLiveChat.chatBuf,indexPtr,xmlTextPtr,xmlTextEnd);
1903 self->chatManager.chatNo = wcstoul(nicoLiveChat.no,NULL,10);
1907 self->chatManager.commentCountSum++;
1908 isReceveChat = TRUE;
1910 check((_heapchk() == _HEAPOK),TEXT("
\83q
\81[
\83v
\83G
\83\89\81[
\82Å
\82·"));
1912 if((wcscmp(nicoLiveChat.chatBuf,L"/disconnect") == 0 && wcscmp(nicoLiveChat.premium,L"2") == 0)){
1915 _beginthread(NicoLiveSelfDisconnect,0,self);
1917 self->callBack(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&nicoLiveChat,self->chatManager.commentCountSum);
1920 //chat_result
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1921 } else if((indexPtr = wcsstr(commentBuf,L"<chat_result ")) != NULL){
1923 indexPtr += wcslen(L"<chat_result ");
1925 nicoLiveSendResultComment = nicoLiveSendResultCommentBase;
1927 while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1928 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1931 nameLen = attrNameEnd - attrNameStart;
1932 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1935 partString(nicoLiveSendResultComment.no,attrValueStart,attrValueEnd);
1937 } else if(wcsncmp(attrNameStart,L"status",nameLen) == 0){
1939 partString(nicoLiveSendResultComment.status,attrValueStart,attrValueEnd);
1942 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1944 partString(nicoLiveSendResultComment.thread,attrValueStart,attrValueEnd);
1947 skipXMLSPACE(indexPtr);
1950 #ifdef USE_NLIB_KEEPALIVE
1951 //
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\83\8a\83Z
\83b
\83g
1952 WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
1953 #endif //USE_NLIB_KEEPALIVE
1955 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSENDRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveSendResultComment,(NICOLIVE_PARAM)NULL);
1961 if(recvBufTmp == recvEndPoint && isReceveChat){
1962 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSETTLE,self,self->option,self->chatManager.chatNo,self->chatManager.commentCountSum);
1968 strcpy(&self->chatManager.recvBuf[0],recvBufTmp);
1985 static void NicoLiveError(void *buf){
1987 NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1989 nl->callBack(NICOLIVE_EVENT_ERR_CONNECT,nl,nl->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
1991 NicoLiveStream_disConnect(nl);
1999 static void NicoLiveSelfDisconnect(void *buf){
2001 NicoLiveStream_P nl = (NicoLiveStream_P)buf;
2003 dumpln(TEXT("selfdisconnect"),);
2005 NicoLiveStream_disConnect(nl);
2015 static INLINE SOCKET GetConectedSocket(LPCTSTR nordName,LPCTSTR port,int socktype,int addr_famiry,int protocol){
2018 SOCKET rslt = INVALID_SOCKET;
2021 PADDRINFOW res,res0;
2023 ZeroMemory(&hints,sizeof(hints));
2024 hints.ai_socktype = socktype;
2025 hints.ai_family = addr_famiry;
2026 hints.ai_protocol = protocol;
2027 GetAddrInfoW(nordName,port,&hints,&res0);
2030 for(res = res0; res != NULL;res = res->ai_next){
2035 rslt = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
2036 if(rslt == INVALID_SOCKET){
2049 if(connect(rslt,res->ai_addr,(int)res->ai_addrlen) == SOCKET_ERROR){
2064 rslt = INVALID_SOCKET;
2068 //res
\8d\
\91¢
\91Ì
\89ð
\95ú
2078 //
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\8aÖ
\98A
2082 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82ÌID
\82ð
\8eæ
\93¾
2084 NLIB_DECLSPEC LPCTSTR NicoLiveStream_getId(NicoLiveStream_P self){
2086 return self->playerStatus.stream.id;
2091 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83R
\83~
\83\85\83j
\83e
\83B
\94Ô
\8d\86\82ð
\8eæ
\93¾
2093 NLIB_DECLSPEC LPCTSTR NicoLiveStream_getDefaultCommunity(NicoLiveStream_P self){
2095 return self->playerStatus.stream.default_community;
2100 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83v
\83\8d\83o
\83C
\83_
\83^
\83C
\83v
\82ð
\8eæ
\93¾
2102 PROVIDERTYPE NicoLiveStream_getProviderType(NicoLiveStream_P self){
2104 return self->playerStatus.stream.provider_type;
2109 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83I
\81[
\83i
\81[
\83t
\83\89\83O
\82ð
\8eæ
\93¾
2111 BOOL NicoLiveStream_isOwner(NicoLiveStream_P self){
2113 return self->playerStatus.stream.is_owner;
2117 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\8aJ
\8en
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2119 time_t NicoLiveStream_getStartTime(NicoLiveStream_P self){
2121 return self->playerStatus.stream.start_time;
2125 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\8fI
\97¹
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2127 time_t NicoLiveStream_getEndTime(NicoLiveStream_P self){
2129 return self->playerStatus.stream.end_time;
2133 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\8aJ
\8fê
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2135 time_t NicoLiveStream_getOpenTime(NicoLiveStream_P self){
2137 return self->playerStatus.stream.open_time;
2142 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83x
\81[
\83X
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2144 time_t NicoLiveStream_getBaseTime(NicoLiveStream_P self){
2146 return self->playerStatus.stream.base_time;
2151 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83^
\83C
\83g
\83\8b\8eæ
\93¾
2153 LPCTSTR NicoLiveStream_getTitle(NicoLiveStream_P self){
2154 #ifdef PLAYERSTATUS_GET_TITLE
2155 return self->playerStatus.stream.title;
2157 static const LPCTSTR rslt = TEXT("");
2162 BOOL NicoLiveStream_isPremium(NicoLiveStream_P self){
2164 return self->playerStatus.user.is_premium;