3 #include "nlib_include.h"
7 //NlibProperty nlibProperty;
12 static XML_Parser xmlParser;
13 static CRITICAL_SECTION playerStatusParserCs;
14 static INT_PTR res_from = 0;
16 static NicoLiveHeartBeatContainer heartBeatContainer;
17 static CRITICAL_SECTION heartBeatCs;
19 static DWORD heartBeatTime = 300000;
21 static BOOL heartBeatFlag = TRUE;
24 static DWORD keapALiveTime = 300000;
26 static BOOL keapALiveFlag = TRUE;
32 #define XMLSPACE L" \t\r\n"
34 #define parseAttr(indexPtr,ans,ane,avs,ave)\
36 (ane) = wcspbrk((ans),XMLSPACE L"=");\
37 (avs) = wcsstr((ane),L"\"") + 1;\
38 (ave) = wcsstr((avs),L"\"");\
39 (indexPtr) = (ave) + 1
41 #define skipXMLSPACE(indexPtr)\
42 for(;(*(indexPtr)) == L' ' || (*(indexPtr)) == '\t' || (*(indexPtr)) == '\r' || (*(indexPtr)) == '\n';indexPtr++)
44 #define partString(ptr,start,end)\
49 #define convertXMLTEXT(buf,basePtr,convPtr,endPtr)\
51 for(;(basePtr) < (endPtr);(basePtr)++,(convPtr)++){\
52 if(wcsncmp((basePtr),L"&",wcslen(L"&")) == 0){\
54 (basePtr) += wcslen(L"&") - 1;\
55 } else if(wcsncmp((basePtr),L"<",wcslen(L"<")) == 0){\
57 (basePtr) += wcslen(L"<") - 1;\
58 } else if(wcsncmp((basePtr),L">",wcslen(L">")) == 0){\
60 (basePtr) += wcslen(L">") - 1;\
61 } else if(wcsncmp((basePtr),L""",wcslen(L""")) == 0){\
62 (convPtr)[0] = L'\"';\
63 (basePtr) += wcslen(L""") - 1;\
64 } else if(wcsncmp((basePtr),L"'",wcslen(L"'")) == 0){\
65 (convPtr)[0] = L'\'';\
66 (basePtr) += wcslen(L"'") - 1;\
68 (convPtr)[0] = (basePtr)[0];\
75 #define convertTEXT(buf,basePtr,convPtr,endPtr)\
77 for(;(basePtr) < (endPtr);(basePtr)++){\
80 strcpy((convPtr),"&");\
81 (convPtr) += strlen(convPtr);\
84 strcpy((convPtr),"<");\
85 (convPtr) += strlen(convPtr);\
88 strcpy((convPtr),">");\
89 (convPtr) += strlen(convPtr);\
92 strcpy((convPtr),""");\
93 (convPtr) += strlen(convPtr);\
96 strcpy((convPtr),"'");\
97 (convPtr) += strlen(convPtr);\
100 WideCharToMultiByte(CP_UTF8,0,(basePtr),1,(convPtr),LENGTH_1024,(LPCSTR)NULL,(LPBOOL)NULL);\
101 (convPtr) += strlen(convPtr);\
111 #define getBaseVpos(server_time,base_time) (((server_time) - (base_time)) * 100)
113 #define setMsec(mSec)\
115 (mSec) = timeGetTime();\
118 #define NicoLiveStream_setVpos(nl,attr)\
119 (nl).chatManager.baseVpos = getBaseVpos((wcstoul((attr),NULL,0)),((nl).playerStatus.stream.base_time));\
120 setMsec((nl).chatManager.commentStartTime)
126 //
\83v
\83\89\83C
\83x
\81[
\83g
\8aÖ
\90\94
130 ///
\83v
\83\8c\83C
\83\84\81[
\83X
\83e
\81[
\83^
\83X
\8eæ
\93¾
132 static INLINE NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P pPlayerStatus,LPCWSTR liveNO,LPCWSTR userSession,HINTERNET hConnect);
135 ///nicoLiveHistory
\8eæ
\93¾
137 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect);
144 ///
\83v
\83\8c\83C
\83\84\81[
\83X
\83e
\81[
\83^
\83X
\83p
\81[
\83T
\8f\89\8aú
\89»
146 static INLINE VOID Parser_Initialize();
150 ///
\83v
\83\8c\83C
\83\84\81[
\83X
\83e
\81[
\83^
\83X
\83p
\81[
\83T
\8cã
\8f\88\97\9d
152 static INLINE VOID Parser_Finalize();
156 ///
\83v
\83\8c\83C
\83\84\81[
\83X
\83e
\81[
\83^
\83X
\83p
\81[
\83X
\8f\88\97\9d
158 static INLINE VOID XMLParse(LPVOID option,LPCSTR body,XML_StartElementHandler startElementEvent,XML_EndElementHandler endElementEvent,XML_CharacterDataHandler characterDataEvent);
163 ///
\83`
\83\83\83b
\83g
\8eó
\90M
\83\8b\81[
\83v
\8aJ
\8en
\8aÖ
\90\94
165 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer);
168 ///
\83n
\81[
\83g
\83r
\81[
\83g
\91\97\90M
\83\8b\81[
\83v
\8aÖ
\90\94
170 static unsigned int WINAPI NicoLiveHeartBeatThread(void* lpBuffer);
174 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\91\97\90M
\83\8b\81[
\83v
\8aÖ
\90\94
176 static unsigned int WINAPI NicoLiveKeapALiveThread(void* lpBuffer);
179 ///
\83`
\83\83\83b
\83g
\8eó
\90M
\83\8b\81[
\83v
\8aÖ
\90\94
181 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self);
185 ///
\83R
\83\81\83\93\83g
\89ð
\90Í
\8aÖ
\90\94
187 static VOID NicoLiveParseComment(NicoLiveStream_P self,LPWSTR commentBuf,UINT_PTR endSize,LPWSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentCountSum,SIZE_T* commentBufSize);
189 static void NicoLiveError(void *buf);
193 ///
\83\
\83P
\83b
\83g
\8eæ
\93¾
\8aÖ
\90\94
195 static INLINE SOCKET GetConectedSocket(LPCWSTR nordName,LPCWSTR port,int socktype,int addr_famiry,int protocol);
197 BOOL Initialize_NicoLive(){
201 //
\83p
\81[
\83T
\82ð
\8f\89\8aú
\89»
204 //
\83n
\81[
\83g
\83r
\81[
\83g
\83R
\83\93\83e
\83i
\8f\89\8aú
\89»
205 ZeroMemory(&heartBeatContainer,sizeof(heartBeatContainer));
206 heartBeatContainer.is_restrictSize = sizeof(WCHAR) * LENGTH_1024;
207 heartBeatContainer.is_restrictBuff = (LPWSTR)calloc(1,heartBeatContainer.is_restrictSize);
208 heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
210 heartBeatContainer.ticketSize = sizeof(WCHAR) * LENGTH_1024;
211 heartBeatContainer.ticketBuff = (LPWSTR)calloc(1,heartBeatContainer.ticketSize);
212 heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
214 InitializeCriticalSection(&heartBeatCs);
224 extern BOOL Finalize_NicoLive(){
227 DeleteCriticalSection(&heartBeatCs);
229 //
\83p
\81[
\83T
\8cã
\8f\88\97\9d
230 free(heartBeatContainer.is_restrictBuff);
231 free(heartBeatContainer.ticketBuff);
234 //
\83v
\83\8c\83C
\83\84\81[
\83X
\83e
\81[
\83^
\83X
\83p
\81[
\83T
\8cã
\8f\88\97\9d
246 NicoLiveStream_P NicoLiveStream_new(){
247 //
\90¶
\90¬&
\8f\89\8aú
\89»
248 NicoLiveStream_P self = (NicoLiveStream_P)calloc(1,sizeof(NicoLiveStream));
250 self->chatManager.endEvent = WSACreateEvent();
252 self->chatManager.startEvent = WSACreateEvent();
254 self->chatManager.deleteEvent = WSACreateEvent();
256 self->chatManager.resetEvents[0] = WSACreateEvent();
258 self->chatManager.resetEvents[1] = WSACreateEvent();
260 self->chatManager.resetEvents[2] = WSACreateEvent();
262 self->chatManager.hRecvChatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveRecvChat,self,0,&self->chatManager.recvChatThreadID);
264 self->chatManager.hHeartBeatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveHeartBeatThread,self,0,&self->chatManager.heartBeatThreadID);
266 self->chatManager.hKeapALiveHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveKeapALiveThread,self,0,&self->chatManager.keapALiveThreadID);
268 dumpln(TEXT("size%d"),sizeof(NicoLiveStream));
278 //
\83j
\83R
\83j
\83R
\90¶
\95ú
\91\97\8aÖ
\98A
\8aÖ
\90\94
279 ///////////////////////////////////////////////////
281 VOID NicoLiveStream_delete(NicoLiveStream_P* self){
283 NicoLiveStream_disConnect((*self));
285 WSASetEvent((*self)->chatManager.deleteEvent);
287 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hRecvChatHandle){
288 WaitForSingleObject( (*self)->chatManager.hRecvChatHandle, INFINITE );
291 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hHeartBeatHandle){
293 WaitForSingleObject((*self)->chatManager.hHeartBeatHandle,INFINITE);
296 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hKeapALiveHandle){
298 WaitForSingleObject((*self)->chatManager.hKeapALiveHandle,INFINITE);
302 CloseHandle((*self)->chatManager.hRecvChatHandle);
304 CloseHandle((*self)->chatManager.hHeartBeatHandle);
306 CloseHandle((*self)->chatManager.hKeapALiveHandle);
308 //
\8cã
\8f\88\97\9d&
\94j
\8aü
310 WSACloseEvent((*self)->chatManager.endEvent);
312 WSACloseEvent((*self)->chatManager.startEvent);
314 WSACloseEvent((*self)->chatManager.deleteEvent);
316 WSACloseEvent((*self)->chatManager.resetEvents[0]);
318 WSACloseEvent((*self)->chatManager.resetEvents[1]);
320 WSACloseEvent((*self)->chatManager.resetEvents[2]);
324 //closesocket(self->chatManager.sock);
329 //nicoLiveStream_Finalize((**self));
333 (*self) = (NicoLiveStream_P)NULL;
340 ///
\83n
\81[
\83g
\83r
\81[
\83g
\82Ì
\8aÔ
\8au
\82ð
\90Ý
\92è
\81i
\83~
\83\8a\95b)
342 VOID SetHeartBeatMsec(DWORD msec){
345 heartBeatTime = msec;
350 ///
\83n
\81[
\83g
\83r
\81[
\83g
\82Ì
\8aÔ
\8au
\82ð
\8eæ
\93¾(
\83~
\83\8a\95b)
352 DWORD GetHeartBeatMsec(){
354 return heartBeatTime;
360 ///
\83n
\81[
\83g
\83r
\81[
\83g
\97L
\8cø
\81E
\96³
\8cø
\90Ý
\92è
362 VOID SetHeartBeatFlag(BOOL flag){
364 heartBeatFlag = flag;
370 ///
\83n
\81[
\83g
\83r
\81[
\83g
\97L
\8cø
\83t
\83\89\83O
\8eæ
\93¾
372 BOOL GetHeartBeatFlag(){
374 return heartBeatFlag;
381 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\82Ì
\8aÔ
\8au
\82ð
\90Ý
\92è(
\83~
\83\8a\95b)
383 VOID SetKeapALiveMsec(DWORD msec){
385 keapALiveTime = msec;
390 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\82Ì
\8aÔ
\8au
\82ð
\8eæ
\93¾(
\83~
\83\8a\95b)
392 DWORD GetKeapALiveMsec(){
394 return keapALiveTime;
400 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\97L
\8cø
\81E
\96³
\8cø
\90Ý
\92è
402 VOID SetKeapALiveFlag(BOOL flag){
404 keapALiveFlag = flag;
409 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\83t
\83\89\83O
\8eæ
\93¾
411 BOOL GetKeapALiveFlag(){
413 return keapALiveFlag;
417 VOID SetResFrom(INT_PTR res){
419 res_from = (-1) * res;
423 INT_PTR GetResFrom(){
425 return (-1) * res_from;
428 NLIB_RESULT NicoLiveStream_connect(NicoLiveStream_P self,NicoVideoAuth_P nicoVideoAuth,LPCWSTR url,NicoRecvCallBack callback,LPVOID option){
430 #define NICOLIVE_CONNECTIONSTREAM_COOKIE_COUNT 1
431 #define LIVENO_LENGTH LENGTH_NICOLIVEID
433 NLIB_RESULT rslt = NLIB_ERR_OK;
441 //url
\82©
\82ç
\90Ú
\91±
\94Ô
\8d\86\82ð
\92\8a\8fo
442 LPCWSTR pInputLiveNo = url;
443 LPCWSTR psrech = wcsstr(url,L"http://");
444 LPCWSTR pInputLiveNoEnd;
445 WCHAR liveNo[LIVENO_LENGTH] = {0};
446 HINTERNET hWatchLiveNicVideo = NULL;
448 //
\91O
\82É
\82Â
\82È
\82¢
\82Å
\82¢
\82½
\95ú
\91\97\82ð
\90Ø
\92f
449 NicoLiveStream_disConnect(self);
455 for(;psrech != NULL;psrech = wcsstr(psrech +1,L"/")){
457 pInputLiveNo = psrech + 1;
463 pInputLiveNoEnd = wcsstr(pInputLiveNo,L"?");
465 if(pInputLiveNoEnd == NULL){
467 pInputLiveNoEnd = pInputLiveNo + wcslen(pInputLiveNo);
471 if(pInputLiveNo == NULL){
473 rslt = NLIB_LIVENO_FAILED_INPUT;
476 }else if(pInputLiveNoEnd - pInputLiveNo + 2 >= LIVENO_LENGTH - 1){
478 rslt = NLIB_LIVENO_FAILED_TOOBIG;
481 } else if((wcsncmp(pInputLiveNo,TEXT("lv"),2) == 0)||(( wcsncmp(pInputLiveNo,TEXT("co"),2) == 0) || (wcsncmp(pInputLiveNo,TEXT("ch"),2) == 0) )){
484 wcsncpy(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
487 } else if(_wtoi(pInputLiveNo) != 0){
489 wcscpy(liveNo,L"lv");
490 wcsncat(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
494 rslt = NLIB_LIVENO_FAILED_UNDEFEINE;
504 wcscpy(self->userSession,nicoVideoAuth->userSession);
508 //watch.live.nicovideo
\82É
\90Ú
\91±
509 hWatchLiveNicVideo = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
511 if(hWatchLiveNicVideo == NULL){
513 rslt = NLIB_ERR_WATCHLIVENICOVIDEO_FAILED_CONNECT;
519 //
\83v
\83\8c\83C
\83\84\81[
\83X
\83e
\81[
\83^
\83X
\8eæ
\93¾
520 rslt = GetPlayerStatus(&self->playerStatus,liveNo,self->userSession,hWatchLiveNicVideo);
522 if(rslt != NLIB_ERR_OK){
527 if(res_from > 0 || res_from < -1000 ){
532 //
\90¶
\95ú
\91\97\83I
\83u
\83W
\83F
\83N
\83g
\82É
\8ae
\88ø
\90\94\82ð
\90Ý
\92è
533 self->res_from = res_from;
534 self->callBack = callback;
535 self->option = option;
538 WSASetEvent(self->chatManager.startEvent);
540 //nicoLiveHistory
\82ð
\8eæ
\93¾(
\95K
\97v
\82È
\82µ
\81H)
541 //GetNicoLiveHistory(self,hWatchLiveNicVideo);
544 WinHttpCloseHandle(hWatchLiveNicVideo);
545 //freeChunkGlobal(chunk);
551 NLIB_RESULT NicoLiveStream_sendHeartBeat(NicoLiveStream_P self){
554 NLIB_RESULT rslt = NLIB_ERR_OK;
556 if(self == NULL || self->playerStatus.error != NLIB_ERR_OK){
558 rslt = NLIB_ERR_PLAYERSTATUS_ERROR;
565 HINTERNET hWatchLiveNicoSession = NULL;
566 HINTERNET hGetPlayerStatusRequest = NULL;
567 ChunkMemory_P chunk = allocChunkGlobal();
569 LPWSTR objectName = (LPWSTR)chunk->buffer;
571 LPWSTR sendBuffer = (LPWSTR)&objectName[LENGTH_4096];
575 DWORD statusCodeSize = sizeof(statusCode);
577 hWatchLiveNicoSession = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
579 wcscpy(objectName,L"/api/heartbeat?v=");
580 indexPtr = objectName + wcslen(objectName);
581 wcscpy(indexPtr,self->playerStatus.stream.id);
582 wcscpy(sendBuffer,L"Cookie: ");
583 indexPtr = sendBuffer + wcslen(sendBuffer);
584 wcscpy(indexPtr,self->userSession);
590 hGetPlayerStatusRequest = WinHttpOpenRequest(hWatchLiveNicoSession,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
592 if(WinHttpSendRequest(hGetPlayerStatusRequest,sendBuffer,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
594 rslt = NLIB_ERR_FAILED_NETWORK;
599 if(WinHttpReceiveResponse(hGetPlayerStatusRequest,NULL) == FALSE){
601 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
607 if (WinHttpQueryHeaders(hGetPlayerStatusRequest,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
608 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
613 if (HTTP_STATUS_OK != statusCode){
614 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
619 recvBuffer = (LPSTR)sendBuffer;
622 if(ReadHttpBody(hGetPlayerStatusRequest,(LPBYTE)recvBuffer,CHUNKMEMORY_MAXSIZE,&readSize) == FALSE){
624 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
632 EnterCriticalSection(&heartBeatCs);
634 XMLParse(&heartBeatContainer,recvBuffer,NicoLiveHeartBeat_ElementStartHandler,NicoLiveHeartBeat_ElementEndHandler,NicoLiveHeartBeat_CharacterDataHandler);
636 self->chatManager.baseVpos = getBaseVpos(heartBeatContainer.heartBeat.time, self->playerStatus.stream.base_time);
637 setMsec(self->chatManager.commentStartTime);
639 self->callBack(NICOLIVE_EVENT_SEND_HEARTBEAT,self,self->option,(NICOLIVE_PARAM)&heartBeatContainer.heartBeat,(NICOLIVE_PARAM)NULL);
641 ZeroMemory(&heartBeatContainer.heartBeat,sizeof(heartBeatContainer.heartBeat));
643 ZeroMemory(heartBeatContainer.is_restrictBuff,heartBeatContainer.is_restrictSize);
645 ZeroMemory(heartBeatContainer.ticketBuff,heartBeatContainer.ticketSize);
647 heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
649 heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
651 LeaveCriticalSection(&heartBeatCs);
657 freeChunkGlobal(chunk);
658 WinHttpCloseHandle(hWatchLiveNicoSession);
659 WinHttpCloseHandle(hGetPlayerStatusRequest);
668 VOID NicoLiveStream_disConnect(NicoLiveStream_P self){
671 WSAResetEvent(self->chatManager.startEvent);
672 WSASetEvent(self->chatManager.endEvent);
678 WSAWaitForMultipleEvents(sizeof(self->chatManager.resetEvents) / sizeof(self->chatManager.resetEvents[0]),self->chatManager.resetEvents,TRUE,WSA_INFINITE,FALSE);
682 WSAEVENT eventObject = self->chatManager.endEvent;
683 WSAEVENT startObject = self->chatManager.startEvent;
684 WSAEVENT deleteObject = self->chatManager.deleteEvent;
685 HANDLE recvThread = self->chatManager.hRecvChatHandle;
686 DWORD recvThreadID = self->chatManager.recvChatThreadID;
688 //nicoLiveStream_Initialize(*self);
689 ZeroMemory(self,sizeof(*self));
690 WSAResetEvent(eventObject);
691 self->chatManager.hRecvChatHandle = recvThread;
692 self->chatManager.recvChatThreadID = recvThreadID;
693 self->chatManager.endEvent = eventObject;
694 self->chatManager.startEvent = startObject;
695 self->chatManager.deleteEvent = deleteObject;
712 #define NICOLIVE_SENDCHATBUFLEN LENGTH_4096
713 #define NICOLIVE_SENDFORMAT "<chat thread=\"%d\" ticket=\"%S\" postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
715 NLIB_RESULT NicoLiveStream_sendChat(NicoLiveStream_P self,LPCWSTR chatbuf,LPCWSTR *mail,LPCWSTR *extends){
719 ChunkMemory_P chunkMemory = allocChunkGlobal();
722 LPSTR postKeyBuf = (LPSTR)chunkMemory->buffer;
723 LPWSTR postKeyReqBuf = (LPWSTR)&postKeyBuf[NICOLIVE_SENDCHATBUFLEN];
724 LPWSTR cookieBuf = &postKeyReqBuf[NICOLIVE_SENDCHATBUFLEN];
726 DWORD statusCodeSize = sizeof(statusCode);
729 HINTERNET hWatchLiveNicoVideo = NULL;
730 HINTERNET hGetPostKeySession = NULL;
731 NLIB_RESULT rslt = NLIB_ERR_OK;
733 if(chatbuf == NULL || wcslen(chatbuf) >= LENGTH_1024){
735 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
742 _swprintf(postKeyReqBuf,L"api/getpostkey?thread=%u&block_no=%u",self->playerStatus.ms.thread,self->chatManager.commentCount / 100);
744 hWatchLiveNicoVideo = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
745 hGetPostKeySession = WinHttpOpenRequest(hWatchLiveNicoVideo,L"GET",postKeyReqBuf,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
748 //_swprintf(cookieBuf,L"Cookie: %s; %s",self->userSession,self->nicoLiveHistory);
749 _swprintf(cookieBuf,L"Cookie: %s",self->userSession);
751 if(WinHttpSendRequest(hGetPostKeySession,cookieBuf,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
753 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
759 if(WinHttpReceiveResponse(hGetPostKeySession,NULL) == FALSE){
761 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
767 if (WinHttpQueryHeaders(hGetPostKeySession,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
768 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
773 if (HTTP_STATUS_OK != statusCode){
774 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
782 if(ReadHttpBody(hGetPostKeySession,(LPBYTE)postKeyBuf,CHUNKMEMORY_MAXSIZE,&readSize) == FALSE){
784 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
788 postKeyBuf[readSize] = '\0';
789 postKey = strstr(postKeyBuf,"=") + 1;
793 LPSTR buffer = (LPSTR)&cookieBuf[NICOLIVE_SENDCHATBUFLEN * 4];
798 //mail
\83R
\83}
\83\93\83h
\8dì
\90¬
805 mailBuf = (LPSTR)postKeyReqBuf;
807 strcpy(indexPtr,"mail=\"");
808 indexPtr += strlen(indexPtr);
810 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
811 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
812 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
817 WideToMB(CP_UTF8,mail[0],indexPtr,len);
818 indexPtr += strlen(indexPtr);
821 for(mail++;mail[0] != NULL;mail++){
826 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
828 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
829 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
834 WideToMB(CP_UTF8,mail[0],indexPtr,len);
835 indexPtr += strlen(indexPtr);
838 strcpy(indexPtr,"\"");
845 //
\8ag
\92£
\91®
\90«
\8dì
\90¬
852 extendBuf =(LPSTR)cookieBuf;
853 indexPtr = extendBuf;
856 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
858 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
859 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
863 WideToMB(CP_UTF8,extends[0],indexPtr,len);
865 indexPtr += strlen(indexPtr);
867 strcpy(indexPtr,"=\"");
868 indexPtr += strlen(indexPtr);
871 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
873 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
874 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
878 WideToMB(CP_UTF8,extends[1],indexPtr,len);
881 for(extends+= 2;extends[0] != NULL;extends+=2){
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);
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);
913 indexPtr += strlen(indexPtr);
914 strcpy(indexPtr,"\"");
920 //
\83`
\83\83\83b
\83g
\91\97\90M
\83R
\83\81\83\93\83g
\8dì
\90¬
923 //
\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>"
924 strcpy(indexPtr,"<chat thread=\"");
925 indexPtr += strlen(indexPtr);
926 sprintf(indexPtr,"%u",self->playerStatus.ms.thread);
927 indexPtr += strlen(indexPtr);
928 strcpy(indexPtr,"\" ticket=\"");
929 indexPtr += strlen(indexPtr);
930 WideToMB(CP_UTF8,self->ticket,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
931 indexPtr += strlen(indexPtr);
932 strcpy(indexPtr,"\" postkey=\"");
933 indexPtr += strlen(indexPtr);
934 strcpy(indexPtr,postKey);
935 indexPtr += strlen(indexPtr);
936 strcpy(indexPtr,"\" user_id=\"");
937 indexPtr += strlen(indexPtr);
938 WideToMB(CP_UTF8,self->playerStatus.user.user_id,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
939 indexPtr += strlen(indexPtr);
940 strcpy(indexPtr,"\" premium=\"");
941 indexPtr += strlen(indexPtr);
942 sprintf(indexPtr,"%u",self->playerStatus.user.is_premium);
943 indexPtr += strlen(indexPtr);
944 strcpy(indexPtr,"\" locale=\"");
945 indexPtr += strlen(indexPtr);
946 WideToMB(CP_UTF8,self->playerStatus.user.userDomain,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
947 indexPtr += strlen(indexPtr);
948 strcpy(indexPtr,"\" vpos=\"");
949 indexPtr += strlen(indexPtr);
953 sprintf(indexPtr,"%u",(self->chatManager.baseVpos + ((timeGetTime() - self->chatManager.commentStartTime) / 10)));
956 indexPtr += strlen(indexPtr);
957 strcpy(indexPtr,"\"");
958 indexPtr += strlen(indexPtr);
960 if(strlen(mailBuf) > 0 && strlen(extendBuf) > 0){
964 strcpy(indexPtr,mailBuf);
965 indexPtr += strlen(indexPtr);
970 strcpy(indexPtr,extendBuf);
971 indexPtr += strlen(indexPtr);
974 } else if(strlen(mailBuf) > 0){
977 strcpy(indexPtr,mailBuf);
978 indexPtr += strlen(indexPtr);
980 } else if(strlen(extendBuf) > 0){
983 strcpy(indexPtr,extendBuf);
984 indexPtr += strlen(indexPtr);
986 strcpy(indexPtr,">");
987 indexPtr += strlen(indexPtr);
989 LPCWSTR endPtr= chatbuf + wcslen(chatbuf);
990 convertTEXT(indexPtr,chatbuf,indexPtr,endPtr);
991 //WideToMB(CP_UTF8,chatbuf,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
992 //indexPtr += strlen(indexPtr);
994 strcpy(indexPtr,"</chat>");
1000 INT_PTR sentLen = 0;
1001 INT_PTR max = strlen(buffer) + 1;
1004 sendLen = send(self->chatManager.sock,buffer,max - sentLen,0);
1006 } while(sendLen > 0);
1019 WinHttpCloseHandle(hGetPostKeySession);
1020 WinHttpCloseHandle(hWatchLiveNicoVideo);
1033 //
\83C
\83\93\83\89\83C
\83\93\8aÖ
\90\94
1038 NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P self,LPCWSTR liveNo,LPCWSTR userSession,HINTERNET hConnect){
1040 NLIB_RESULT rslt = NLIB_ERR_OK;
1042 HINTERNET hWatchLiveNicoSession = NULL;
1043 HINTERNET hGetPlayerStatusRequest = NULL;
1044 ChunkMemory_P chunkMemory = (ChunkMemory_P)NULL;
1050 DWORD statusCodeSize = sizeof(statusCode);
1052 #define GETPLAYERSTATUS_OBJECTNAME_LENGTH LENGTH_256
1054 WCHAR objectName[GETPLAYERSTATUS_OBJECTNAME_LENGTH] = {L"api/getplayerstatus?v="};
1055 const SIZE_T objectNameLen = wcslen(objectName);
1056 LPWSTR liveNoTmp = &objectName[objectNameLen];
1058 if(wcslen(liveNo) > GETPLAYERSTATUS_OBJECTNAME_LENGTH - objectNameLen - 1){
1060 rslt = NLIB_LIVENO_FAILED_TOOBIG;
1063 } else if(wcslen(userSession) > LENGTH_4096){
1065 rslt = NLIB_USERSESSION_FAILED_TOOBIG;
1070 chunkMemory = allocChunkGlobal();
1071 buffer = getBufChunk(chunkMemory);
1072 sendBuffer = (LPWSTR)buffer;
1073 wcscpy(sendBuffer,L"Cookie: ");
1074 wcscat(sendBuffer,userSession);
1077 wcscpy(liveNoTmp,liveNo);
1079 if(hConnect == NULL){
1080 hWatchLiveNicoSession = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
1083 hWatchLiveNicoSession = hConnect;
1087 hGetPlayerStatusRequest = WinHttpOpenRequest(hWatchLiveNicoSession,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1089 if(WinHttpSendRequest(hGetPlayerStatusRequest,sendBuffer,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1091 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1096 if(WinHttpReceiveResponse(hGetPlayerStatusRequest,NULL) == FALSE){
1098 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1104 if (WinHttpQueryHeaders(hGetPlayerStatusRequest,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1105 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1110 if (HTTP_STATUS_OK != statusCode){
1111 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1116 recvBuffer = (LPSTR)sendBuffer;
1119 if(ReadHttpBody(hGetPlayerStatusRequest,(LPBYTE)recvBuffer,CHUNKMEMORY_MAXSIZE,&readSize) == FALSE){
1121 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1126 recvBuffer[readSize] = '\0';
1128 recvBuffer = strstr(recvBuffer,"<");
1130 dumpln_mb(CP_UTF8,"%s",recvBuffer);
1133 XMLParse(self,recvBuffer,NPlayerStatus_ElementStartHandler,NPlayerStatus_ElementEndHandler,NPlayerStatus_CharacterDataHandler);
1135 if(rslt != NLIB_ERR_OK){
1143 freeChunkGlobal(chunkMemory);
1144 WinHttpCloseHandle(hGetPlayerStatusRequest);
1146 //hConnect
\82ªNULL
\8ew
\92è
\82Å
\93n
\82³
\82ê
\82½
\8fê
\8d\87\81A
\82±
\82Ì
\8aÖ
\90\94\82Å
\83n
\83\93\83h
\83\8b\82ð
\90¶
\90¬
\82µ
\82½
\82Ì
\82Å
\95Â
\82¶
\82é
1147 if(hConnect == NULL){
1148 WinHttpCloseHandle(hWatchLiveNicoSession);
1156 #define GETNICOLIVEHIS_OBJNAMELENGTH LENGTH_256
1157 #define GETNICOLIVEHIS_COOKIELENGTH LENGTH_512
1159 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect){
1161 NLIB_RESULT rslt = NLIB_ERR_OK;
1163 HINTERNET hNicoVideoConnect = NULL;
1164 HINTERNET hStreamBrowse = NULL;
1167 WCHAR objectName[GETNICOLIVEHIS_OBJNAMELENGTH] = {L"/watch/"};
1168 WCHAR cookie[GETNICOLIVEHIS_COOKIELENGTH] = {L"Cookie: "};
1170 DWORD statusCodeSize = sizeof(statusCode);
1171 ChunkMemory_P chunkMemory = allocChunkGlobal();
1172 DWORD chunkSize = CHUNKMEMORY_MAXSIZE;
1175 LPWSTR buffer = (LPWSTR)chunkMemory->buffer;
1179 if((GETNICOLIVEHIS_OBJNAMELENGTH - wcslen(objectName) <= wcslen(self->playerStatus.stream.id)) || GETNICOLIVEHIS_COOKIELENGTH - wcslen(cookie) <= wcslen(self->userSession)){
1181 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1185 wcscat(objectName,self->playerStatus.stream.id);
1186 wcscat(cookie,self->userSession);
1188 if(hConnect == NULL){
1190 hNicoVideoConnect = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
1194 hNicoVideoConnect = hConnect;
1198 hStreamBrowse = WinHttpOpenRequest(hNicoVideoConnect,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1203 if(WinHttpSendRequest(hStreamBrowse,cookie,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1205 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1210 if(WinHttpReceiveResponse(hStreamBrowse,NULL) == FALSE){
1212 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1217 if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1218 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1223 if (HTTP_STATUS_OK != statusCode){
1224 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1230 if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_SET_COOKIE,WINHTTP_HEADER_NAME_BY_INDEX,buffer,&chunkSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1231 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1236 LPWSTR start =wcsstr(buffer,L"nicolivehistory=");
1238 LPWSTR end = wcsstr(start,L";");
1240 UINT_PTR length = end - start;
1242 if(length >= sizeof(self->nicoLiveHistory)){
1243 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1248 wcsncpy(self->nicoLiveHistory,start,length);
1249 self->nicoLiveHistory[length] = L'\0';
1253 freeChunkGlobal(chunkMemory);
1254 WinHttpCloseHandle(hStreamBrowse);
1256 if(hConnect == NULL){
1258 WinHttpCloseHandle(hNicoVideoConnect);
1272 static INLINE VOID Parser_Initialize(){
1275 xmlParser = XML_ParserCreate((const XML_Char*)NULL);
1277 check(xmlParser,TEXT("
\83p
\81[
\83T
\8f\89\8aú
\89»
\82É
\8e¸
\94s
\82µ
\82Ü
\82µ
\82½"));
1281 InitializeCriticalSection(&playerStatusParserCs);
1285 static INLINE VOID Parser_Finalize(){
1288 XML_ParserFree(xmlParser);
1290 DeleteCriticalSection(&playerStatusParserCs);
1295 static INLINE VOID XMLParse(LPVOID option,LPCSTR body,XML_StartElementHandler startElementEvent,XML_EndElementHandler endElementEvent,XML_CharacterDataHandler characterDataEvent){
1297 UserDataContainer userDataContainer;
1298 userDataContainer.nord = 0;
1299 userDataContainer.userData = option;
1302 EnterCriticalSection(&playerStatusParserCs);
1305 XML_SetElementHandler(xmlParser,startElementEvent,endElementEvent);
1306 XML_SetCharacterDataHandler(xmlParser,characterDataEvent);
1307 XML_SetUserData(xmlParser,&userDataContainer);
1310 XML_Parse(xmlParser,body,strlen(body),TRUE);
1312 //
\83\8a\83Z
\83b
\83g
1313 XML_ParserReset(xmlParser,(const XML_Char*)NULL);
1315 LeaveCriticalSection(&playerStatusParserCs);
1320 static unsigned int WINAPI NicoLiveKeapALiveThread(void* lpBuffer){
1322 unsigned int rslt = 0;
1324 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1326 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1327 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1332 WSASetEvent(self->chatManager.resetEvents[2]);
1334 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1337 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1338 if(dwResult == WSA_WAIT_FAILED){
1344 switch(dwResult - WSA_WAIT_EVENT_0){
1363 endResult = WSAWaitForMultipleEvents(1,&self->chatManager.endEvent,FALSE,keapALiveTime,FALSE);
1365 if(endResult == WSA_WAIT_TIMEOUT){
1368 LPCWSTR mail[2] = {L"184",NULL};
1369 NicoLiveStream_sendChat(self,L"/keapalive",mail,NULL);
1371 } else if(endResult - WSA_WAIT_EVENT_0 == 0){
1385 _beginthread(NicoLiveError,0,self);
1394 static unsigned int WINAPI NicoLiveHeartBeatThread(void* lpBuffer){
1396 unsigned int rslt = 0;
1398 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1400 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1401 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1406 WSASetEvent(self->chatManager.resetEvents[1]);
1408 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1411 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1412 if(dwResult == WSA_WAIT_FAILED){
1418 switch(dwResult - WSA_WAIT_EVENT_0){
1437 endResult = WSAWaitForMultipleEvents(1,&self->chatManager.endEvent,FALSE,heartBeatTime,FALSE);
1439 if(endResult == WSA_WAIT_TIMEOUT){
1442 NicoLiveStream_sendHeartBeat(self);
1444 } else if(endResult - WSA_WAIT_EVENT_0 == 0){
1458 _beginthread(NicoLiveError,0,self);
1468 #define NICOLIVE_RECEVE_CHAT_LENGTH LENGTH_2048
1469 #define NICOLIVE_REQUEST_CHAT_LENGTH LENGTH_256
1470 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer){
1473 unsigned int rslt = 0;
1475 //LPWSTR user_id = NULL;
1476 //LPWSTR name = NULL;
1477 //LPWSTR chatBuf = NULL;
1481 CHAR requestChat[NICOLIVE_REQUEST_CHAT_LENGTH]; //
\91\97\90M
\93d
\95¶
\97p
\83o
\83b
\83t
\83@
1482 LPCSTR sendFormat = "<thread thread=\"%u\" res_from=\"%d\" version=\"20061206\" />"; //
\91\97\90M
\93d
\95¶
\83t
\83H
\81[
\83}
\83b
\83g
1483 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer; //
\83j
\83R
\90¶
\95ú
\91\97\83I
\83u
\83W
\83F
\83N
\83g
1484 INT_PTR sendLen; //
\91\97\90M
\97p
\95¶
\8e\9a\90\94
1485 INT_PTR sentLen; //
\91\97\90M
\8dÏ
\82Ý
\95¶
\8e\9a\90\94
1486 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1487 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1493 WSASetEvent(self->chatManager.resetEvents[0]);
1495 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1498 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1499 if(dwResult == WSA_WAIT_FAILED){
1505 switch(dwResult - WSA_WAIT_EVENT_0){
1527 //
\83\
\83P
\83b
\83g
\82Ì
\90Ý
\92è
1528 self->chatManager.sock = GetConectedSocket(self->playerStatus.ms.addr,self->playerStatus.ms.port,SOCK_STREAM,AF_INET,IPPROTO_TCP);
1531 //
\83R
\83\81\83\93\83g
\8eó
\90M
\8aJ
\8en
\82Ì
\89º
\8f\80\94õ
1532 if(self->chatManager.sock == INVALID_SOCKET){
1533 self->error = NLIB_ERR_FAILED_NETWORK;
1542 if(NICOLIVE_REQUEST_CHAT_LENGTH <= _scprintf(sendFormat,self->playerStatus.ms.thread,self->res_from)){
1544 self->error = NLIB_ERR_BUFFER_TOOLITTLE;
1551 sprintf(requestChat,sendFormat,self->playerStatus.ms.thread,self->res_from);
1555 //
\83R
\83\81\83\93\83g
\8eó
\90M
\97v
\8b\81\91\97\90M
\8f\88\97\9d
1559 sendLen = strlen(requestChat) + 1;
1561 len = send(self->chatManager.sock,requestChat,sendLen,0);
1562 if(len == SOCKET_ERROR){
1563 self->error = NLIB_ERR_FAILED_NETWORK;
1571 }while(sentLen < sendLen);
1575 if(NicoLiveRecvChatLoop(self) == FALSE){
1585 _beginthread(NicoLiveError,0,self);
1591 closesocket(self->chatManager.sock);
1603 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self){
1607 //
\83R
\83\81\83\93\83g
\8eó
\90M
\8f\88\97\9d
1609 BOOL rslt = TRUE; //
\8c\8b\89Ê
1610 LPWSTR commentBuf = NULL; //
\83R
\83\81\83\93\83g
\83o
\83b
\83t
\83@
1611 LPWSTR* mailCountBuf = NULL; //
\83\81\81[
\83\8b\83|
\83C
\83\93\83^
\83o
\83b
\83t
\83@
1612 INT_PTR recevedLen; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\92·
1613 INT_PTR messageBufLen; //
\83o
\83b
\83t
\83@
\92·
1617 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ñ
1618 WSANETWORKEVENTS netEvents; //
\83l
\83b
\83g
\83\8f\81[
\83N
\83C
\83x
\83\93\83g
1619 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
1622 SIZE_T commentBufSize = sizeof(WCHAR) * LENGTH_2048; //
\83R
\83\81\83\93\83g
\83o
\83b
\83t
\83@
\92·
1623 SIZE_T mailCountBufSize = sizeof(LPWSTR) * LENGTH_256; //
\83\81\81[
\83\8b\82Ì
\83|
\83C
\83\93\83^
\97p
\83o
\83b
\83t
\83@
\92·
1629 SIZE_T commentCountSum = 0; //
\83R
\83\81\83\93\83g
\83J
\83E
\83\93\83g
1630 WSAEVENT hRecvEvent = NULL;
1632 //
\8eó
\90M
\8f\80\94õ
\8f\88\97\9d
1633 hRecvEvent = WSACreateEvent();
1634 self->chatManager.recvBuf[0] = '\0';
1635 WSAEventSelect(self->chatManager.sock, hRecvEvent, FD_READ | FD_CLOSE);
1636 hEventArray[0] = hRecvEvent;
1637 hEventArray[1] = self->chatManager.endEvent;
1639 commentBuf = (LPWSTR)malloc(commentBufSize);
1640 mailCountBuf = (LPWSTR*)malloc(mailCountBufSize);
1642 //
\90Ø
\92f
\82³
\82ê
\82é
\82Ü
\82Å
\83\8b\81[
\83v
1647 //
\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é
1648 messageBufLen = strlen(self->chatManager.recvBuf);
1650 //
\8eó
\90M
\82©
\8fI
\97¹
\83C
\83x
\83\93\83g
\82ð
\8c\9f\92m
\82·
\82é
\82Ü
\82Å
\91Ò
\8b@
1651 dwResult = WSAWaitForMultipleEvents(sizeof(hEventArray) / sizeof(hEventArray[0]),hEventArray,FALSE,WSA_INFINITE,FALSE);
1653 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1654 if(dwResult == WSA_WAIT_FAILED){
1661 //
\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
1662 if(dwResult - WSA_WAIT_EVENT_0 == 0){
1664 WSAEnumNetworkEvents(self->chatManager.sock,hRecvEvent,&netEvents);
1666 //
\93Ç
\8eæ
\83C
\83x
\83\93\83g
\82Ì
\8fê
\8d\87\83R
\83\81\83\93\83g
\82ð
\8eó
\90M
\82·
\82é
1667 if(netEvents.lNetworkEvents & FD_READ){
1670 recevedLen = recv(self->chatManager.sock,&self->chatManager.recvBuf[messageBufLen],(sizeof(self->chatManager.recvBuf) - 1) - messageBufLen ,0);
1672 if(recevedLen == SOCKET_ERROR){
1673 self->error = NLIB_ERR_FAILED_NETWORK;
1678 self->chatManager.recvBuf[messageBufLen + recevedLen] = '\0';
1685 NicoLiveParseComment(self,commentBuf,messageBufLen + recevedLen,mailCountBuf,&mailCountBufSize,&commentCountSum,&commentBufSize);
1691 } else if(netEvents.lNetworkEvents && FD_CLOSE){
1695 }//if(netEvents.lNetworkEvents & FD_READ)
1697 } else if(dwResult - WSA_WAIT_EVENT_0 == 1){
1701 }//if(dwResult - WSA_WAIT_EVENT_0 == 0)
1713 WSACloseEvent(hRecvEvent);
1719 static VOID NicoLiveParseComment(NicoLiveStream_P self,LPWSTR commentBuf,UINT_PTR endSize,LPWSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentCountSum,SIZE_T* commentBufSize){
1721 LPWSTR indexPtr; //
\89ð
\90Í
\8e\9e\82Ì
\8ew
\95W
\83|
\83C
\83\93\83^
1722 NicoLiveChat nicoLiveChat; //
\83`
\83\83\83b
\83g
\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1723 NicoLiveThreadComment nicoLiveThreadComment; //
\90Ú
\91±
\89\9e\93\9a\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1724 NicoLiveSendResultComment nicoLiveSendResultComment; //
\91\97\90M
\89\9e\93\9a\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1725 NicoLiveChat nicoLiveChatBase; //
\83`
\83\83\83b
\83g
\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1726 NicoLiveThreadComment nicoLiveThreadCommentBase; //
\90Ú
\91±
\89\9e\93\9a\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1727 NicoLiveSendResultComment nicoLiveSendResultCommentBase;//
\91\97\90M
\89\9e\93\9a\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1728 LPWSTR attrNameStart; //
\91®
\90«
\96¼
\8aJ
\8en
\83|
\83C
\83\93\83^
1729 LPWSTR attrNameEnd; //
\91®
\90«
\96¼
\8fI
\97¹
\83|
\83C
\83\93\83^
1730 LPWSTR attrValueStart; //
\91®
\90«
\92l
\8aJ
\8en
\83|
\83C
\83\93\83^
1731 LPWSTR attrValueEnd; //
\91®
\90«
\92l
\8fI
\97¹
\83|
\83C
\83\93\83^
1732 INT_PTR nameLen; //
\91®
\90«
\82Ì
\96¼
\91O
\82Ì
\92·
\82³
1733 LPWSTR mailIndexPtr; //
\83\81\81[
\83\8b\91®
\90«
\92l
\89ð
\90Í
\97p
\8ew
\95W
\83|
\83C
\83\93\83^
1734 LPWSTR xmlTextPtr; //xml
\83e
\83L
\83X
\83g
\8c`
\8e®
\82Ì
\83f
\81[
\83^
\89ð
\90Í
\8e\9e\82É
\8eg
\97p
\82·
\82é
\83|
\83C
\83\93\83^
1735 LPWSTR xmlTextEnd; //xml
\83e
\83L
\83X
\83g
\8fI
\97¹
\83|
\83C
\83\93\83^
1736 LPWSTR* mailIndex; //
\83\81\81[
\83\8b\83R
\83}
\83\93\83h
\83\8a\83X
\83g
\83|
\83C
\83\93\83^
1737 BOOL isReceveChat = FALSE; //
\83`
\83\83\83b
\83g
\8eó
\90M
\83t
\83\89\83O
1738 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³
1739 LPSTR recvBufTmp; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\91\80\8dì
\97p
\83|
\83C
\83\93\83^
1740 LPSTR recvEndPoint; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\8fI
\92[
\83|
\83C
\83\93\83^
1744 recvBufTmp = &self->chatManager.recvBuf[0];
1745 recvEndPoint = &self->chatManager.recvBuf[endSize];
1748 //
\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
\8f\89\8aú
\89»
1749 nicoLiveChatBase.anonymity = L"";
1750 nicoLiveChatBase.chatBuf = L"";
1751 nicoLiveChatBase.date = L"";
1752 nicoLiveChatBase.locale = L"";
1753 nicoLiveChatBase.mail = mailCountBuf;
1754 nicoLiveChatBase.name = L"";
1755 nicoLiveChatBase.no = L"";
1756 nicoLiveChatBase.premium = L"";
1757 nicoLiveChatBase.thread = L"";
1758 nicoLiveChatBase.user_id = L"";
1759 nicoLiveChatBase.vpos = L"";
1760 nicoLiveChatBase.mailCount = 0;
1764 nicoLiveThreadCommentBase.last_res = L"";
1765 nicoLiveThreadCommentBase.thread = L"";
1766 nicoLiveThreadCommentBase.ticket = L"";
1769 nicoLiveSendResultCommentBase.no = L"";
1770 nicoLiveSendResultCommentBase.status = L"";
1771 nicoLiveSendResultCommentBase.thread = L"";
1774 //
\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é
1775 for (;recvBufTmp + strlen(recvBufTmp) < recvEndPoint;recvBufTmp += strlen(recvBufTmp) + 1){
1778 commentSizeCh = sizeof(WCHAR) * GetLenToWide(CP_UTF8,recvBufTmp);
1779 extendMalloc(commentBuf,LPWSTR,*commentBufSize,commentSizeCh);
1780 MBToWide(CP_UTF8,recvBufTmp,commentBuf,*commentBufSize);
1782 traceln(TEXT("comment:\r\n%s"),commentBuf);
1783 //thread
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1784 if((indexPtr = wcsstr(commentBuf,L"<thread ")) != NULL){
1786 indexPtr += wcslen(L"<thread ");
1787 skipXMLSPACE(indexPtr);
1792 nicoLiveThreadComment = nicoLiveThreadCommentBase;
1794 while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1795 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1798 nameLen = attrNameEnd - attrNameStart;
1799 if(wcsncmp(attrNameStart,L"ticket",nameLen) == 0){
1802 partString(nicoLiveThreadComment.ticket,attrValueStart,attrValueEnd);
1803 wcscpy(self->ticket,nicoLiveThreadComment.ticket);
1805 } else if(wcsncmp(attrNameStart,L"last_res",nameLen) == 0){
1807 partString(nicoLiveThreadComment.last_res,attrValueStart,attrValueEnd);
1810 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1812 partString(nicoLiveThreadComment.thread,attrValueStart,attrValueEnd);
1813 } else if(wcsncmp(attrNameStart,L"server_time",nameLen) == 0){
1815 NicoLiveStream_setVpos((*self),attrValueStart);
1817 partString(nicoLiveThreadComment.server_time,attrValueStart,attrValueEnd);
1820 skipXMLSPACE(indexPtr);
1825 self->callBack(NICOLIVE_EVENT_RECEVE_CONNECTRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveThreadComment,self->chatManager.commentCount);
1827 //chat
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1828 } else if((indexPtr = wcsstr(commentBuf,L"<chat ")) != NULL){
1830 indexPtr += wcslen(L"<chat ");
1831 skipXMLSPACE(indexPtr);
1836 nicoLiveChat = nicoLiveChatBase;
1838 while(wcsncmp(indexPtr,L">",wcslen(L">"))){
1840 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1842 nameLen = attrNameEnd - attrNameStart;
1845 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1847 partString(nicoLiveChat.no,attrValueStart,attrValueEnd);
1849 } else if(wcsncmp(attrNameStart,L"date",nameLen) == 0){
1851 NicoLiveStream_setVpos((*self),attrValueStart);
1853 partString(nicoLiveChat.date,attrValueStart,attrValueEnd);
1855 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1857 partString(nicoLiveChat.thread,attrValueStart,attrValueEnd);
1859 } else if(wcsncmp(attrNameStart,L"premium",nameLen) == 0){
1861 partString(nicoLiveChat.premium,attrValueStart,attrValueEnd);
1863 } else if(wcsncmp(attrNameStart,L"anonymity",nameLen) == 0){
1865 partString(nicoLiveChat.anonymity,attrValueStart,attrValueEnd);
1868 } else if(wcsncmp(attrNameStart,L"locale",nameLen) == 0){
1870 partString(nicoLiveChat.locale,attrValueStart,attrValueEnd);
1872 } else if(wcsncmp(attrNameStart,L"vpos",nameLen) == 0){
1874 partString(nicoLiveChat.vpos,attrValueStart,attrValueEnd);
1876 } else if(wcsncmp(attrNameStart,L"user_id",nameLen) == 0){
1878 partString(nicoLiveChat.user_id,attrValueStart,attrValueEnd);
1880 } else if(wcsncmp(attrNameStart,L"name",nameLen) == 0){
1882 partString(nicoLiveChat.name,attrNameStart,attrValueEnd);
1884 } else if(wcsncmp(attrNameStart,L"mail",nameLen) == 0){
1886 nicoLiveChat.mailCount = 1;
1889 for(mailIndexPtr = attrValueStart;mailIndexPtr <= attrValueEnd;mailIndexPtr++){
1891 if(mailIndexPtr[0] == L' '){
1893 nicoLiveChat.mailCount++;
1899 extendMalloc(mailCountBuf,LPWSTR*,*mailCountBufSize,nicoLiveChat.mailCount);
1901 nicoLiveChat.mail = mailCountBuf;
1902 mailCountBuf[0] = NULL;
1904 for(mailIndex = mailCountBuf,mailIndexPtr = attrValueStart,mailIndex[0] = mailIndexPtr;mailIndexPtr < attrValueEnd;mailIndexPtr++){
1907 if(mailIndexPtr[0] == L' '){
1909 mailIndex[0] = mailIndexPtr + 1;
1910 mailIndexPtr[0] = L'\0';
1917 mailIndexPtr[0] = L'\0';
1921 skipXMLSPACE(indexPtr);
1925 xmlTextPtr = indexPtr;
1926 xmlTextEnd = wcsstr(indexPtr,L"<");
1927 convertXMLTEXT(nicoLiveChat.chatBuf,indexPtr,xmlTextPtr,xmlTextEnd);
1932 self->chatManager.commentCount = wcstoul(nicoLiveChat.no,NULL,0);
1933 (*commentCountSum)++;
1934 isReceveChat = TRUE;
1935 self->callBack(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&nicoLiveChat,self->chatManager.commentCount);
1938 //chat_result
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1939 } else if((indexPtr = wcsstr(commentBuf,L"<chat_result ")) != NULL){
1941 indexPtr += wcslen(L"<chat_result ");
1943 nicoLiveSendResultComment = nicoLiveSendResultCommentBase;
1945 while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1946 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1949 nameLen = attrNameEnd - attrNameStart;
1950 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1953 partString(nicoLiveSendResultComment.no,attrValueStart,attrValueEnd);
1955 } else if(wcsncmp(attrNameStart,L"status",nameLen) == 0){
1957 partString(nicoLiveSendResultComment.status,attrValueStart,attrValueEnd);
1960 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1962 partString(nicoLiveSendResultComment.thread,attrValueStart,attrValueEnd);
1965 skipXMLSPACE(indexPtr);
1968 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSENDRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveSendResultComment,(NICOLIVE_PARAM)NULL);
1974 if(recvBufTmp == recvEndPoint && isReceveChat){
1975 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSETTLE,self,self->option,self->chatManager.commentCount,*commentCountSum);
1981 strcpy(&self->chatManager.recvBuf[0],recvBufTmp);
1996 static void NicoLiveError(void *buf){
1998 NicoLiveStream_P nl = (NicoLiveStream_P)buf;
2000 nl->callBack(NICOLIVE_EVENT_ERR_CONNECT,nl,nl->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
2002 NicoLiveStream_disConnect(nl);
2010 static INLINE SOCKET GetConectedSocket(LPCWSTR nordName,LPCWSTR port,int socktype,int addr_famiry,int protocol){
2013 SOCKET rslt = INVALID_SOCKET;
2016 PADDRINFOW res,res0;
2018 ZeroMemory(&hints,sizeof(hints));
2019 hints.ai_socktype = socktype;
2020 hints.ai_family = addr_famiry;
2021 hints.ai_protocol = protocol;
2022 GetAddrInfoW(nordName,port,&hints,&res0);
2025 for(res = res0; res != NULL;res = res->ai_next){
2030 rslt = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
2031 if(rslt == INVALID_SOCKET){
2044 if(connect(rslt,res->ai_addr,(int)res->ai_addrlen) == SOCKET_ERROR){
2059 rslt = INVALID_SOCKET;
2063 //res
\8d\
\91¢
\91Ì
\89ð
\95ú