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);
109 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\91\97\90M
\83\8b\81[
\83v
\8aÖ
\90\94
111 static unsigned int WINAPI NicoLiveKeapALiveThread(void* lpBuffer);
117 ///
\83`
\83\83\83b
\83g
\8eó
\90M
\83\8b\81[
\83v
\8aÖ
\90\94
119 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self);
124 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend,LPDWORD time);
127 ///
\83R
\83\81\83\93\83g
\89ð
\90Í
\8aÖ
\90\94
129 static VOID NicoLiveParseComment(NicoLiveStream_P self,LPTSTR commentBuf,UINT_PTR endSize,LPTSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize);
131 static void NicoLiveError(void *buf);
133 static void NicoLiveSelfDisconnect(void *buf);
135 static VOID OnSendHeartBeat(NicoLiveStream_P self);
137 static VOID OnSendKeepAllive(NicoLiveStream_P self);
139 ///
\83\
\83P
\83b
\83g
\8eæ
\93¾
\8aÖ
\90\94
141 static INLINE SOCKET GetConectedSocket(LPCTSTR nordName,LPCTSTR port,int socktype,int addr_famiry,int protocol);
144 StreamStatus_P NicoLiveStream_getStreamStatus(NicoLiveStream_P self){
146 return &self->playerStatus.stream;
149 BOOL Initialize_NicoLive(){
155 //
\83n
\81[
\83g
\83r
\81[
\83g
\83R
\83\93\83e
\83i
\8f\89\8aú
\89»
156 ZeroMemory(&heartBeatContainer,sizeof(heartBeatContainer));
157 heartBeatContainer.is_restrictSize = sizeof(TCHAR) * LENGTH_1024;
158 heartBeatContainer.is_restrictBuff = (LPTSTR)calloc(1,heartBeatContainer.is_restrictSize);
159 heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
161 heartBeatContainer.ticketSize = sizeof(TCHAR) * LENGTH_1024;
162 heartBeatContainer.ticketBuff = (LPTSTR)calloc(1,heartBeatContainer.ticketSize);
163 heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
165 InitializeCriticalSection(&heartBeatCs);
175 extern BOOL Finalize_NicoLive(){
178 DeleteCriticalSection(&heartBeatCs);
180 //
\83p
\81[
\83T
\8cã
\8f\88\97\9d
181 free(heartBeatContainer.is_restrictBuff);
182 free(heartBeatContainer.ticketBuff);
196 NicoLiveStream_P NicoLiveStream_new(){
197 //
\90¶
\90¬&
\8f\89\8aú
\89»
198 NicoLiveStream_P self = (NicoLiveStream_P)calloc(1,sizeof(NicoLiveStream));
200 //
\8f\89\8aú
\92l
\82Ì
\90Ý
\92è
201 self->chatManager.onHeartBeatSend = OnSendHeartBeat;
203 self->chatManager.onKeepAlliveSend = OnSendKeepAllive;
205 InitializeCriticalSection(&self->sessionManager.cs);
207 self->chatManager.heartBeatTime = 300000;
209 self->chatManager.heartBeatFlag = FALSE;
211 self->chatManager.keepAliveTime = 900000;
213 self->chatManager.keapALiveFlag = TRUE;
215 self->isConnecting = FALSE;
217 self->chatManager.endEvent = WSACreateEvent();
219 self->chatManager.startEvent = WSACreateEvent();
221 self->chatManager.deleteEvent = WSACreateEvent();
223 self->chatManager.setHeartBeatTimeEvent = WSACreateEvent();
225 self->chatManager.setKeepAliveTimeEvent = WSACreateEvent();
227 self->chatManager.resetEvents[0] = WSACreateEvent();
229 self->chatManager.resetEvents[1] = WSACreateEvent();
231 self->chatManager.resetEvents[2] = WSACreateEvent();
237 //
\83X
\83\8c\83b
\83h
\82Ì
\8aJ
\8en
238 self->chatManager.hRecvChatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveRecvChat,self,0,&self->chatManager.recvChatThreadID);
240 self->chatManager.hHeartBeatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveHeartBeatThread,self,0,&self->chatManager.heartBeatThreadID);
242 self->chatManager.hKeapALiveHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveKeapALiveThread,self,0,&self->chatManager.keapALiveThreadID);
251 //
\83j
\83R
\83j
\83R
\90¶
\95ú
\91\97\8aÖ
\98A
\8aÖ
\90\94
252 ///////////////////////////////////////////////////
254 VOID NicoLiveStream_delete(NicoLiveStream_P* self){
256 NicoLiveStream_disConnect((*self));
258 WSASetEvent((*self)->chatManager.deleteEvent);
260 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hRecvChatHandle){
261 WaitForSingleObject( (*self)->chatManager.hRecvChatHandle, INFINITE );
262 CloseHandle((*self)->chatManager.hRecvChatHandle);
265 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hHeartBeatHandle){
267 WaitForSingleObject((*self)->chatManager.hHeartBeatHandle,INFINITE);
268 CloseHandle((*self)->chatManager.hHeartBeatHandle);
271 if(INVALID_HANDLE_VALUE != (*self)->chatManager.hKeapALiveHandle){
273 WaitForSingleObject((*self)->chatManager.hKeapALiveHandle,INFINITE);
274 CloseHandle((*self)->chatManager.hKeapALiveHandle);
284 //
\8cã
\8f\88\97\9d&
\94j
\8aü
286 DeleteCriticalSection(&(*self)->sessionManager.cs);
288 WSACloseEvent((*self)->chatManager.setHeartBeatTimeEvent);
290 WSACloseEvent((*self)->chatManager.setKeepAliveTimeEvent);
292 WSACloseEvent((*self)->chatManager.endEvent);
294 WSACloseEvent((*self)->chatManager.startEvent);
296 WSACloseEvent((*self)->chatManager.deleteEvent);
298 WSACloseEvent((*self)->chatManager.resetEvents[0]);
300 WSACloseEvent((*self)->chatManager.resetEvents[1]);
302 WSACloseEvent((*self)->chatManager.resetEvents[2]);
309 (*self) = (NicoLiveStream_P)NULL;
316 ///
\83n
\81[
\83g
\83r
\81[
\83g
\82Ì
\8aÔ
\8au
\82ð
\90Ý
\92è
\81i
\83~
\83\8a\95b)
318 VOID NicoLiveStream_setHeartBeatMsec(NicoLiveStream_P self,DWORD msec){
321 self->chatManager.heartBeatTime = msec;
322 WSASetEvent(self->chatManager.setHeartBeatTimeEvent);
327 ///
\83n
\81[
\83g
\83r
\81[
\83g
\82Ì
\8aÔ
\8au
\82ð
\8eæ
\93¾(
\83~
\83\8a\95b)
329 DWORD NicoLiveStream_getHeartBeatMsec(NicoLiveStream_P self){
331 return self->chatManager.heartBeatTime;
337 ///
\83n
\81[
\83g
\83r
\81[
\83g
\97L
\8cø
\81E
\96³
\8cø
\90Ý
\92è
339 VOID NicoLiveStream_setHeartBeatFlag(NicoLiveStream_P self,BOOL flag){
341 self->chatManager.heartBeatFlag = flag;
347 ///
\83n
\81[
\83g
\83r
\81[
\83g
\97L
\8cø
\83t
\83\89\83O
\8eæ
\93¾
349 BOOL NicoLiveStream_getHeartBeatFlag(NicoLiveStream_P self){
351 return self->chatManager.heartBeatFlag;
358 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\82Ì
\8aÔ
\8au
\82ð
\90Ý
\92è(
\83~
\83\8a\95b)
360 VOID NicoLiveStream_setKeapALiveMsec(NicoLiveStream_P self,DWORD msec){
363 self->chatManager.keepAliveTime = msec;
364 WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
370 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\82Ì
\8aÔ
\8au
\82ð
\8eæ
\93¾(
\83~
\83\8a\95b)
372 DWORD NicoLiveStream_getKeapALiveMsec(NicoLiveStream_P self){
374 return self->chatManager.keepAliveTime;
380 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\97L
\8cø
\81E
\96³
\8cø
\90Ý
\92è
382 VOID NicoLiveStream_setKeapALiveFlag(NicoLiveStream_P self,BOOL flag){
384 self->chatManager.keapALiveFlag = flag;
389 ///
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\83t
\83\89\83O
\8eæ
\93¾
391 BOOL NicoLiveStream_getKeapALiveFlag(NicoLiveStream_P self){
393 return self->chatManager.keapALiveFlag;
397 VOID NicoLiveStrream_setResFrom(NicoLiveStream_P self,INT_PTR res){
401 self->res_from = (res < 0 || res > 1000) ? 0 : ((-1) * res);
405 INT_PTR NicoLiveStream_getResFrom(NicoLiveStream_P self){
407 return (-1) * self->res_from;
410 NLIB_RESULT NicoLiveStream_connect(NicoLiveStream_P self,NicoVideoAuth_P nicoVideoAuth,LPCTSTR url,NicoRecvCallBack callback,LPVOID option){
412 #define NICOLIVE_CONNECTIONSTREAM_COOKIE_COUNT 1
413 #define LIVENO_LENGTH LENGTH_NICOLIVEID
415 NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
423 //url
\82©
\82ç
\90Ú
\91±
\94Ô
\8d\86\82ð
\92\8a\8fo
424 LPCTSTR pInputLiveNo = url;
425 LPCTSTR psrech = wcsstr(url,L"http://");
426 LPCTSTR pInputLiveNoEnd;
427 TCHAR liveNo[LIVENO_LENGTH] = {0};
430 if(self == NULL)goto end;
432 //
\91O
\82É
\82Â
\82È
\82¢
\82Å
\82¢
\82½
\95ú
\91\97\82ð
\90Ø
\92f
433 NicoLiveStream_disConnect(self);
439 for(;psrech != NULL;psrech = wcsstr(psrech +1,L"/")){
441 pInputLiveNo = psrech + 1;
447 pInputLiveNoEnd = wcsstr(pInputLiveNo,L"?");
449 if(pInputLiveNoEnd == NULL){
451 pInputLiveNoEnd = pInputLiveNo + wcslen(pInputLiveNo);
455 if(pInputLiveNo == NULL){
457 rslt = NLIB_LIVENO_IS_NULL;
460 }else if(pInputLiveNoEnd - pInputLiveNo + 2 >= LIVENO_LENGTH - 1){
462 rslt = NLIB_LIVENO_FAILED_TOOBIG;
465 } else if((wcsncmp(pInputLiveNo,TEXT("lv"),2) == 0)||(( wcsncmp(pInputLiveNo,TEXT("co"),2) == 0) || (wcsncmp(pInputLiveNo,TEXT("ch"),2) == 0) )){
468 wcsncpy(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
471 } else if(_wtoi(pInputLiveNo) != 0){
473 wcscpy(liveNo,L"lv");
474 wcsncat(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
478 rslt = NLIB_LIVENO_FAILED_UNDEFEINE;
487 wcsncpy(self->userSession,L"Cookie: ",sizeof(self->userSession) / sizeof(self->userSession[0]) - 1);
488 wcsncat(self->userSession,nicoVideoAuth->userSession,sizeof(self->userSession) / sizeof(self->userSession[0]) - 1);
489 self->userSession[sizeof(self->userSession) / sizeof(self->userSession[0]) - 1] = L'\0';
495 TCHAR objectName[LENGTH_256] = {L"api/getplayerstatus?v="};
496 wcsncat(objectName,liveNo,sizeof(objectName) / sizeof(objectName[0]));
502 self->sessionManager.getPlayerStatusSession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",objectName,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
505 //
\83v
\83\8c\83C
\83\84\81[
\83X
\83e
\81[
\83^
\83X
\8eæ
\93¾
506 EnterCriticalSection(&self->sessionManager.cs);
507 rslt = GetPlayerStatus(&self->playerStatus,self->userSession,self->sessionManager.getPlayerStatusSession,self->sessionManager.buffer);
508 LeaveCriticalSection(&self->sessionManager.cs);
510 if(rslt != NLIB_ERR_OK){
517 //
\90¶
\95ú
\91\97\83I
\83u
\83W
\83F
\83N
\83g
\82É
\8ae
\88ø
\90\94\82ð
\90Ý
\92è
519 self->callBack = callback;
520 self->option = option;
523 WSASetEvent(self->chatManager.startEvent);
525 self->isConnecting = TRUE;
529 //nicoLiveHistory
\82ð
\8eæ
\93¾(
\95K
\97v
\82È
\82µ
\81H)
530 //GetNicoLiveHistory(self,hWatchLiveNicVideo);
539 NLIB_RESULT NicoLiveStream_sendHeartBeat(NicoLiveStream_P self){
542 NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
544 if(self->isConnecting == FALSE){
545 rslt = NLIB_ERR_NOT_LIVECONNECT;
548 if(self == NULL || self->playerStatus.error != NLIB_ERR_OK){
550 rslt = NLIB_ERR_PLAYERSTATUS_ERROR;
556 EnterCriticalSection(&self->sessionManager.cs);
558 //HINTERNET hWatchLiveNicoSession = NULL;
559 //HINTERNET hGetPlayerStatusRequest = NULL;
560 const UINT_PTR buflen = LENGTH_65536;
561 LPVOID buffer = self->sessionManager.buffer;
563 LPTSTR objectName = (LPTSTR)buffer;
565 //LPTSTR sendBuffer = (LPTSTR)&objectName[LENGTH_4096];
566 LPSTR recvBuffer = (LPSTR)&objectName[LENGTH_4096];
569 DWORD statusCodeSize = sizeof(statusCode);
571 //hWatchLiveNicoSession = hWatchLiveNicoConnect;
573 wcscpy(objectName,L"/api/heartbeat?v=");
574 indexPtr = objectName + wcslen(objectName);
575 wcscpy(indexPtr,self->playerStatus.stream.id);
576 //wcscpy(sendBuffer,L"Cookie: ");
577 //indexPtr = sendBuffer + wcslen(sendBuffer);
578 wcscpy(indexPtr,self->userSession);
583 if(self->sessionManager.heartBeatSession == NULL){
584 self->sessionManager.heartBeatSession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",objectName,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
587 if(WinHttpSendRequest(self->sessionManager.heartBeatSession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
589 rslt = NLIB_ERR_FAILED_NETWORK;
594 if(WinHttpReceiveResponse(self->sessionManager.heartBeatSession,NULL) == FALSE){
596 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
602 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){
603 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
608 if (HTTP_STATUS_OK != statusCode){
609 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
614 //recvBuffer = (LPSTR)sendBuffer;
617 if(ReadHttpBody(self->sessionManager.heartBeatSession,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
619 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
627 EnterCriticalSection(&heartBeatCs);
629 XMLParse(&heartBeatContainer,recvBuffer,NicoLiveHeartBeat_ElementStartHandler,NicoLiveHeartBeat_ElementEndHandler,NicoLiveHeartBeat_CharacterDataHandler);
631 self->chatManager.baseVpos = getBaseVpos(heartBeatContainer.heartBeat.time, self->playerStatus.stream.base_time);
632 setMsec(self->chatManager.commentStartTime);
634 self->callBack(NICOLIVE_EVENT_SEND_HEARTBEAT,self,self->option,(NICOLIVE_PARAM)&heartBeatContainer.heartBeat,(NICOLIVE_PARAM)NULL);
636 ZeroMemory(&heartBeatContainer.heartBeat,sizeof(heartBeatContainer.heartBeat));
638 ZeroMemory(heartBeatContainer.is_restrictBuff,heartBeatContainer.is_restrictSize);
640 ZeroMemory(heartBeatContainer.ticketBuff,heartBeatContainer.ticketSize);
642 heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
644 heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
646 LeaveCriticalSection(&heartBeatCs);
653 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
654 LeaveCriticalSection(&self->sessionManager.cs);
666 VOID NicoLiveStream_disConnect(NicoLiveStream_P self){
668 if(self == NULL)goto end;
670 while(WSAResetEvent(self->chatManager.startEvent) == FALSE);
671 while(WSASetEvent(self->chatManager.endEvent)== FALSE);
677 WSAWaitForMultipleEvents(sizeof(self->chatManager.resetEvents) / sizeof(self->chatManager.resetEvents[0]),self->chatManager.resetEvents,TRUE,WSA_INFINITE,FALSE);
681 //nicoLiveStream_Initialize(*self);
682 ZeroMemory(&self->playerStatus,sizeof(self->playerStatus));
683 WSAResetEvent(self->chatManager.endEvent);
685 WinHttpCloseHandle(self->sessionManager.getPlayerStatusSession);
686 self->sessionManager.getPlayerStatusSession = NULL;
687 WinHttpCloseHandle(self->sessionManager.heartBeatSession);
688 self->sessionManager.heartBeatSession = NULL;
692 self->isConnecting = FALSE;
704 #define NICOLIVE_SENDCHATBUFLEN LENGTH_4096
705 #define NICOLIVE_SENDFORMAT "<chat thread=\"%d\" ticket=\"%S\" postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
707 NLIB_RESULT NicoLiveStream_sendChat(NicoLiveStream_P self,LPCTSTR chatbuf,LPCTSTR *mail,LPCTSTR *extends){
709 NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
710 EnterCriticalSection(&self->sessionManager.cs);
713 const UINT_PTR buflen = LENGTH_65536 * 4;
714 LPVOID chunk = self->sessionManager.buffer;
717 LPSTR postKeyBuf = (LPSTR)chunk;
718 LPTSTR postKeyReqBuf = (LPTSTR)&postKeyBuf[NICOLIVE_SENDCHATBUFLEN];
719 LPTSTR cookieBuf = &postKeyReqBuf[NICOLIVE_SENDCHATBUFLEN];
721 DWORD statusCodeSize = sizeof(statusCode);
724 //HINTERNET hWatchLiveNicoVideo = NULL;
725 HINTERNET hGetPostKeySession = NULL;
728 if(self->isConnecting == FALSE){
729 rslt = NLIB_ERR_NOT_LIVECONNECT;
732 if(chatbuf == NULL || wcslen(chatbuf) >= LENGTH_1024){
734 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
741 _swprintf(postKeyReqBuf,L"api/getpostkey?thread=%u&block_no=%u",self->playerStatus.ms.thread,self->chatManager.chatNo / 100);
743 //hWatchLiveNicoVideo = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
744 hGetPostKeySession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",postKeyReqBuf,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
747 //_swprintf(cookieBuf,L"Cookie: %s; %s",self->userSession,self->nicoLiveHistory);
748 _swprintf(cookieBuf,L"Cookie: %s",self->userSession);
750 if(WinHttpSendRequest(hGetPostKeySession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
752 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
758 if(WinHttpReceiveResponse(hGetPostKeySession,NULL) == FALSE){
760 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
766 if (WinHttpQueryHeaders(hGetPostKeySession,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
767 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
772 if (HTTP_STATUS_OK != statusCode){
773 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
781 if(ReadHttpBody(hGetPostKeySession,(LPBYTE)postKeyBuf,buflen,&readSize) == FALSE){
783 rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
787 postKeyBuf[readSize] = '\0';
788 postKey = strstr(postKeyBuf,"=") + 1;
792 LPSTR buffer = (LPSTR)&cookieBuf[NICOLIVE_SENDCHATBUFLEN];
797 //mail
\83R
\83}
\83\93\83h
\8dì
\90¬
798 if(mail == NULL || mail[0] == NULL){
804 mailBuf = (LPSTR)postKeyReqBuf;
806 strcpy(indexPtr,"mail=\"");
807 indexPtr += strlen(indexPtr);
809 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
810 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
811 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);
839 strcpy(indexPtr,"\"");
846 //
\8ag
\92£
\91®
\90«
\8dì
\90¬
847 if(extends == NULL || extends[0] == NULL){
853 extendBuf =(LPSTR)cookieBuf;
854 indexPtr = extendBuf;
857 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
859 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
860 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
864 WideToMB(CP_UTF8,extends[0],indexPtr,len);
866 indexPtr += strlen(indexPtr);
868 strcpy(indexPtr,"=\"");
869 indexPtr += strlen(indexPtr);
872 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
874 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
875 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
879 WideToMB(CP_UTF8,extends[1],indexPtr,len);
882 for(extends+= 2;extends[0] != NULL;extends+=2){
887 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
889 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
890 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
894 WideToMB(CP_UTF8,extends[0],indexPtr,len);
896 indexPtr += strlen(indexPtr);
902 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
904 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
905 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
909 WideToMB(CP_UTF8,extends[1],indexPtr,len);
914 indexPtr += strlen(indexPtr);
915 strcpy(indexPtr,"\"");
921 //
\83`
\83\83\83b
\83g
\91\97\90M
\83R
\83\81\83\93\83g
\8dì
\90¬
924 //
\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>"
925 strcpy(indexPtr,"<chat thread=\"");
926 indexPtr += strlen(indexPtr);
927 sprintf(indexPtr,"%u",self->playerStatus.ms.thread);
928 indexPtr += strlen(indexPtr);
929 strcpy(indexPtr,"\" ticket=\"");
930 indexPtr += strlen(indexPtr);
931 WideToMB(CP_UTF8,self->ticket,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
932 indexPtr += strlen(indexPtr);
933 strcpy(indexPtr,"\" postkey=\"");
934 indexPtr += strlen(indexPtr);
935 strcpy(indexPtr,postKey);
936 indexPtr += strlen(indexPtr);
937 strcpy(indexPtr,"\" user_id=\"");
938 indexPtr += strlen(indexPtr);
939 WideToMB(CP_UTF8,self->playerStatus.user.user_id,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
940 indexPtr += strlen(indexPtr);
941 strcpy(indexPtr,"\" premium=\"");
942 indexPtr += strlen(indexPtr);
943 sprintf(indexPtr,"%u",self->playerStatus.user.is_premium);
944 indexPtr += strlen(indexPtr);
945 strcpy(indexPtr,"\" locale=\"");
946 indexPtr += strlen(indexPtr);
947 WideToMB(CP_UTF8,self->playerStatus.user.userDomain,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
948 indexPtr += strlen(indexPtr);
949 strcpy(indexPtr,"\" vpos=\"");
950 indexPtr += strlen(indexPtr);
954 sprintf(indexPtr,"%u",(self->chatManager.baseVpos + ((timeGetTime() - self->chatManager.commentStartTime) / 10)));
957 indexPtr += strlen(indexPtr);
958 strcpy(indexPtr,"\"");
959 indexPtr += strlen(indexPtr);
961 if(strlen(mailBuf) > 0 && strlen(extendBuf) > 0){
965 strcpy(indexPtr,mailBuf);
966 indexPtr += strlen(indexPtr);
971 strcpy(indexPtr,extendBuf);
972 indexPtr += strlen(indexPtr);
975 } else if(strlen(mailBuf) > 0){
978 strcpy(indexPtr,mailBuf);
979 indexPtr += strlen(indexPtr);
981 } else if(strlen(extendBuf) > 0){
984 strcpy(indexPtr,extendBuf);
985 indexPtr += strlen(indexPtr);
987 strcpy(indexPtr,">");
988 indexPtr += strlen(indexPtr);
990 LPTSTR sendBuf = (LPTSTR)&buffer[NICOLIVE_SENDCHATBUFLEN * 4];
991 LPTSTR sendPtr = sendBuf;
992 LPCTSTR endPtr= chatbuf + wcslen(chatbuf);
995 //convertTEXT(indexPtr,chatbuf,indexPtr,endPtr);
997 for(;(chatbuf) <= (endPtr);(chatbuf)++){
1000 wcscpy((sendBuf),L"&");
1001 (sendBuf) += wcslen(sendBuf);
1004 wcscpy((sendBuf),L"<");
1005 (sendBuf) += wcslen(sendBuf);
1008 wcscpy((sendBuf),L">");
1009 (sendBuf) += wcslen(sendBuf);
1012 wcscpy((sendBuf),L""");
1013 (sendBuf) += wcslen(sendBuf);
1016 wcscpy((sendBuf),L"'");
1017 (sendBuf) += wcslen(sendBuf);
1020 sendBuf[0] = chatbuf[0];
1027 WideToMB(CP_UTF8,sendPtr,indexPtr,NICOLIVE_SENDCHATBUFLEN * 4 - (indexPtr - buffer) - 1);
1028 indexPtr += strlen(indexPtr);
1031 strcpy(indexPtr,"</chat>");
1032 indexPtr[strlen(indexPtr)] = '\0';
1037 INT_PTR sendLen = 0;
1038 INT_PTR sentLen = 0;
1039 INT_PTR max = strlen(buffer) + 1;
1042 sendLen = send(self->chatManager.sock,buffer,max - sentLen,0);
1044 } while(sendLen > 0);
1054 WinHttpCloseHandle(hGetPostKeySession);
1056 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1057 LeaveCriticalSection(&self->sessionManager.cs);
1073 //
\83C
\83\93\83\89\83C
\83\93\8aÖ
\90\94
1078 NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P self,LPCTSTR userSession,HINTERNET hConnect,LPVOID buffer){
1080 NLIB_RESULT rslt = NLIB_ERR_OK;
1084 //HINTERNET hWatchLiveNicoSession = NULL;
1085 //HINTERNET hGetPlayerStatusRequest = NULL;
1086 const UINT_PTR buflen = LENGTH_65536;
1088 //LPTSTR sendBuffer;
1089 LPSTR recvBuffer = (LPSTR)buffer;
1092 DWORD statusCodeSize = sizeof(statusCode);
1097 if(WinHttpSendRequest(hConnect,userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1099 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1104 if(WinHttpReceiveResponse(hConnect,NULL) == FALSE){
1106 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1112 if (WinHttpQueryHeaders(hConnect,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1113 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1118 if (HTTP_STATUS_OK != statusCode){
1119 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1124 //recvBuffer = (LPSTR)sendBuffer;
1127 if(ReadHttpBody(hConnect,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
1129 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1134 recvBuffer[readSize] = '\0';
1136 recvBuffer = strstr(recvBuffer,"<");
1138 dumpln_mb(CP_UTF8,"%s",recvBuffer);
1141 XMLParse(self,recvBuffer,NPlayerStatus_ElementStartHandler,NPlayerStatus_ElementEndHandler,NPlayerStatus_CharacterDataHandler);
1143 if(rslt != NLIB_ERR_OK){
1160 #define GETNICOLIVEHIS_OBJNAMELENGTH LENGTH_256
1161 #define GETNICOLIVEHIS_COOKIELENGTH LENGTH_512
1163 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect){
1165 NLIB_RESULT rslt = NLIB_ERR_OK;
1167 EnterCriticalSection(&self->sessionManager.cs);
1169 //HINTERNET hNicoVideoConnect = NULL;
1170 HINTERNET hStreamBrowse = NULL;
1173 TCHAR objectName[GETNICOLIVEHIS_OBJNAMELENGTH] = {L"/watch/"};
1174 TCHAR cookie[GETNICOLIVEHIS_COOKIELENGTH] = {L"Cookie: "};
1176 DWORD statusCodeSize = sizeof(statusCode);
1177 DWORD chunkSize = LENGTH_65536;
1178 LPVOID chunkMemory =self->sessionManager.buffer;
1182 LPTSTR buffer = (LPTSTR)chunkSize;
1186 if((GETNICOLIVEHIS_OBJNAMELENGTH - wcslen(objectName) <= wcslen(self->playerStatus.stream.id)) || GETNICOLIVEHIS_COOKIELENGTH - wcslen(cookie) <= wcslen(self->userSession)){
1188 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1192 wcscat(objectName,self->playerStatus.stream.id);
1193 wcscat(cookie,self->userSession);
1197 //hNicoVideoConnect = hConnect;
1201 hStreamBrowse = WinHttpOpenRequest(hNicoVideoConnect,L"GET",objectName,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1206 if(WinHttpSendRequest(hStreamBrowse,cookie,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1208 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1213 if(WinHttpReceiveResponse(hStreamBrowse,NULL) == FALSE){
1215 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1220 if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1221 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1226 if (HTTP_STATUS_OK != statusCode){
1227 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1233 if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_SET_COOKIE,WINHTTP_HEADER_NAME_BY_INDEX,buffer,&chunkSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1234 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1239 LPTSTR start =wcsstr(buffer,L"nicolivehistory=");
1241 LPTSTR end = wcsstr(start,L";");
1243 UINT_PTR length = end - start;
1245 if(length >= sizeof(self->nicoLiveHistory)){
1246 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1251 wcsncpy(self->nicoLiveHistory,start,length);
1252 self->nicoLiveHistory[length] = L'\0';
1257 WinHttpCloseHandle(hStreamBrowse);
1260 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1261 LeaveCriticalSection(&self->sessionManager.cs);
1277 static unsigned int WINAPI NicoLiveKeapALiveThread(void* lpBuffer){
1279 unsigned int rslt = 0;
1281 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1283 rslt = loopCommon(self,self->chatManager.setKeepAliveTimeEvent,self->chatManager.resetEvents[2],self->chatManager.onKeepAlliveSend,&self->chatManager.keepAliveTime);
1290 static unsigned int WINAPI NicoLiveHeartBeatThread(void* lpBuffer){
1292 unsigned int rslt = 0;
1294 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1297 rslt = loopCommon(self,self->chatManager.setHeartBeatTimeEvent,self->chatManager.resetEvents[1],self->chatManager.onHeartBeatSend,&self->chatManager.heartBeatTime);
1305 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend,LPDWORD time){
1307 unsigned int rslt = 0;
1308 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1309 WSAEVENT streamEvent[2] = {self->chatManager.endEvent,sendEvent};
1310 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1315 WSASetEvent(resetEvent);
1317 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1320 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1321 if(dwResult == WSA_WAIT_FAILED){
1327 switch(dwResult - WSA_WAIT_EVENT_0){
1334 WSAResetEvent(resetEvent);
1348 WSAResetEvent(sendEvent);
1349 endResult = WSAWaitForMultipleEvents(sizeof(streamEvent) / sizeof(streamEvent[0]),streamEvent,FALSE,*time,FALSE);
1351 if(endResult == WSA_WAIT_TIMEOUT){
1353 nicoLiveOnSend(self);
1354 //dumpln(TEXT("onSend"));
1358 switch(endResult - WSA_WAIT_EVENT_0){
1381 _beginthread(NicoLiveError,0,self);
1386 static VOID OnSendHeartBeat(NicoLiveStream_P self){
1388 if(self->chatManager.heartBeatFlag){
1389 NicoLiveStream_sendHeartBeat(self);
1394 static VOID OnSendKeepAllive(NicoLiveStream_P self){
1396 if(self->chatManager.keapALiveFlag){
1397 LPCTSTR mail[2] = {L"184",NULL};
1398 NicoLiveStream_sendChat(self,L"/keapalive",mail,NULL);
1403 #define NICOLIVE_RECEVE_CHAT_LENGTH LENGTH_2048
1404 #define NICOLIVE_REQUEST_CHAT_LENGTH LENGTH_256
1405 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer){
1408 unsigned int rslt = 0;
1410 //LPTSTR user_id = NULL;
1411 //LPTSTR name = NULL;
1412 //LPTSTR chatBuf = NULL;
1416 CHAR requestChat[NICOLIVE_REQUEST_CHAT_LENGTH]; //
\91\97\90M
\93d
\95¶
\97p
\83o
\83b
\83t
\83@
1417 LPCSTR sendFormat = "<thread thread=\"%u\" res_from=\"%d\" version=\"20061206\" />"; //
\91\97\90M
\93d
\95¶
\83t
\83H
\81[
\83}
\83b
\83g
1418 NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer; //
\83j
\83R
\90¶
\95ú
\91\97\83I
\83u
\83W
\83F
\83N
\83g
1419 INT_PTR sendLen; //
\91\97\90M
\97p
\95¶
\8e\9a\90\94
1420 INT_PTR sentLen; //
\91\97\90M
\8dÏ
\82Ý
\95¶
\8e\9a\90\94
1421 WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent}; //
\83C
\83x
\83\93\83g
\94z
\97ñ
1422 DWORD dwResult; //
\83C
\83x
\83\93\83g
\8eó
\90M
\8c\8b\89Ê
1428 WSASetEvent(self->chatManager.resetEvents[0]);
1430 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1433 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1434 if(dwResult == WSA_WAIT_FAILED){
1440 switch(dwResult - WSA_WAIT_EVENT_0){
1447 WSAResetEvent(self->chatManager.resetEvents[0]);
1463 //
\83\
\83P
\83b
\83g
\82Ì
\90Ý
\92è
1464 self->chatManager.sock = GetConectedSocket(self->playerStatus.ms.addr,self->playerStatus.ms.port,SOCK_STREAM,AF_INET,IPPROTO_TCP);
1467 //
\83R
\83\81\83\93\83g
\8eó
\90M
\8aJ
\8en
\82Ì
\89º
\8f\80\94õ
1468 if(self->chatManager.sock == INVALID_SOCKET){
1469 self->error = NLIB_ERR_FAILED_NETWORK;
1478 if(NICOLIVE_REQUEST_CHAT_LENGTH <= _scprintf(sendFormat,self->playerStatus.ms.thread,self->res_from)){
1480 self->error = NLIB_ERR_BUFFER_TOOLITTLE;
1487 sprintf(requestChat,sendFormat,self->playerStatus.ms.thread,self->res_from);
1491 //
\83R
\83\81\83\93\83g
\8eó
\90M
\97v
\8b\81\91\97\90M
\8f\88\97\9d
1495 sendLen = strlen(requestChat) + 1;
1497 len = send(self->chatManager.sock,requestChat,sendLen,0);
1498 if(len == SOCKET_ERROR){
1499 self->error = NLIB_ERR_FAILED_NETWORK;
1507 }while(sentLen < sendLen);
1511 if(NicoLiveRecvChatLoop(self) == FALSE){
1523 _beginthread(NicoLiveError,0,self);
1529 closesocket(self->chatManager.sock);
1544 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self){
1548 //
\83R
\83\81\83\93\83g
\8eó
\90M
\8f\88\97\9d
1550 BOOL rslt = TRUE; //
\8c\8b\89Ê
1551 LPTSTR commentBuf = NULL; //
\83R
\83\81\83\93\83g
\83o
\83b
\83t
\83@
1552 LPTSTR* mailCountBuf = NULL; //
\83\81\81[
\83\8b\83|
\83C
\83\93\83^
\83o
\83b
\83t
\83@
1553 INT_PTR recevedLen; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\92·
1554 INT_PTR messageBufLen; //
\83o
\83b
\83t
\83@
\92·
1558 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ñ
1559 WSANETWORKEVENTS netEvents; //
\83l
\83b
\83g
\83\8f\81[
\83N
\83C
\83x
\83\93\83g
1560 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
1563 SIZE_T commentBufSize = sizeof(TCHAR) * LENGTH_2048; //
\83R
\83\81\83\93\83g
\83o
\83b
\83t
\83@
\92·
1564 SIZE_T mailCountBufSize = sizeof(LPTSTR) * LENGTH_256; //
\83\81\81[
\83\8b\82Ì
\83|
\83C
\83\93\83^
\97p
\83o
\83b
\83t
\83@
\92·
1567 WSAEVENT hRecvEvent = NULL;
1569 //
\8eó
\90M
\8f\80\94õ
\8f\88\97\9d
1570 self->chatManager.commentCountSum = 0;
1571 hRecvEvent = WSACreateEvent();
1572 self->chatManager.recvBuf[0] = '\0';
1573 WSAEventSelect(self->chatManager.sock, hRecvEvent, FD_READ | FD_CLOSE);
1574 hEventArray[0] = hRecvEvent;
1575 hEventArray[1] = self->chatManager.endEvent;
1577 commentBuf = (LPTSTR)malloc(commentBufSize);
1578 mailCountBuf = (LPTSTR*)malloc(mailCountBufSize);
1580 //
\90Ø
\92f
\82³
\82ê
\82é
\82Ü
\82Å
\83\8b\81[
\83v
1585 //
\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é
1586 messageBufLen = strlen(self->chatManager.recvBuf);
1588 //
\8eó
\90M
\82©
\8fI
\97¹
\83C
\83x
\83\93\83g
\82ð
\8c\9f\92m
\82·
\82é
\82Ü
\82Å
\91Ò
\8b@
1589 dwResult = WSAWaitForMultipleEvents(sizeof(hEventArray) / sizeof(hEventArray[0]),hEventArray,FALSE,WSA_INFINITE,FALSE);
1591 //
\83G
\83\89\81[
\82Ì
\8fê
\8d\87
1592 if(dwResult == WSA_WAIT_FAILED){
1599 //
\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
1600 if(dwResult - WSA_WAIT_EVENT_0 == 0){
1602 WSAEnumNetworkEvents(self->chatManager.sock,hRecvEvent,&netEvents);
1604 //
\93Ç
\8eæ
\83C
\83x
\83\93\83g
\82Ì
\8fê
\8d\87\83R
\83\81\83\93\83g
\82ð
\8eó
\90M
\82·
\82é
1605 if(netEvents.lNetworkEvents & FD_READ){
1608 recevedLen = recv(self->chatManager.sock,&self->chatManager.recvBuf[messageBufLen],(sizeof(self->chatManager.recvBuf) - 1) - messageBufLen ,0);
1610 if(recevedLen == SOCKET_ERROR){
1611 self->error = NLIB_ERR_FAILED_NETWORK;
1616 self->chatManager.recvBuf[messageBufLen + recevedLen] = '\0';
1623 NicoLiveParseComment(self,commentBuf,messageBufLen + recevedLen,mailCountBuf,&mailCountBufSize,&commentBufSize);
1629 } else if(netEvents.lNetworkEvents && FD_CLOSE){
1633 }//if(netEvents.lNetworkEvents & FD_READ)
1635 } else if(dwResult - WSA_WAIT_EVENT_0 == 1){
1639 }//if(dwResult - WSA_WAIT_EVENT_0 == 0)
1651 WSACloseEvent(hRecvEvent);
1659 static VOID NicoLiveParseComment(NicoLiveStream_P self,LPTSTR commentBuf,UINT_PTR endSize,LPTSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize){
1661 LPTSTR indexPtr; //
\89ð
\90Í
\8e\9e\82Ì
\8ew
\95W
\83|
\83C
\83\93\83^
1662 NicoLiveChat nicoLiveChat; //
\83`
\83\83\83b
\83g
\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1663 NicoLiveThreadComment nicoLiveThreadComment; //
\90Ú
\91±
\89\9e\93\9a\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1664 NicoLiveSendResultComment nicoLiveSendResultComment; //
\91\97\90M
\89\9e\93\9a\83R
\83\81\83\93\83g
\8ai
\94[
\97p
\8d\
\91¢
\91Ì
1665 NicoLiveChat nicoLiveChatBase; //
\83`
\83\83\83b
\83g
\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1666 NicoLiveThreadComment nicoLiveThreadCommentBase; //
\90Ú
\91±
\89\9e\93\9a\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1667 NicoLiveSendResultComment nicoLiveSendResultCommentBase;//
\91\97\90M
\89\9e\93\9a\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
1668 LPTSTR attrNameStart; //
\91®
\90«
\96¼
\8aJ
\8en
\83|
\83C
\83\93\83^
1669 LPTSTR attrNameEnd; //
\91®
\90«
\96¼
\8fI
\97¹
\83|
\83C
\83\93\83^
1670 LPTSTR attrValueStart; //
\91®
\90«
\92l
\8aJ
\8en
\83|
\83C
\83\93\83^
1671 LPTSTR attrValueEnd; //
\91®
\90«
\92l
\8fI
\97¹
\83|
\83C
\83\93\83^
1672 INT_PTR nameLen; //
\91®
\90«
\82Ì
\96¼
\91O
\82Ì
\92·
\82³
1673 LPTSTR mailIndexPtr; //
\83\81\81[
\83\8b\91®
\90«
\92l
\89ð
\90Í
\97p
\8ew
\95W
\83|
\83C
\83\93\83^
1674 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^
1675 LPTSTR xmlTextEnd; //xml
\83e
\83L
\83X
\83g
\8fI
\97¹
\83|
\83C
\83\93\83^
1676 LPTSTR* mailIndex; //
\83\81\81[
\83\8b\83R
\83}
\83\93\83h
\83\8a\83X
\83g
\83|
\83C
\83\93\83^
1677 BOOL isReceveChat = FALSE; //
\83`
\83\83\83b
\83g
\8eó
\90M
\83t
\83\89\83O
1678 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³
1679 LPSTR recvBufTmp; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\91\80\8dì
\97p
\83|
\83C
\83\93\83^
1680 LPSTR recvEndPoint; //
\8eó
\90M
\95¶
\8e\9a\97ñ
\8fI
\92[
\83|
\83C
\83\93\83^
1684 recvBufTmp = &self->chatManager.recvBuf[0];
1685 recvEndPoint = &self->chatManager.recvBuf[endSize];
1688 //
\83R
\83\81\83\93\83g
\8aî
\92ê
\8d\
\91¢
\91Ì
\8f\89\8aú
\89»
1689 nicoLiveChatBase.anonymity = L"";
1690 nicoLiveChatBase.chatBuf = L"";
1691 nicoLiveChatBase.date = L"";
1692 nicoLiveChatBase.locale = L"";
1693 nicoLiveChatBase.mail = mailCountBuf;
1694 nicoLiveChatBase.name = L"";
1695 nicoLiveChatBase.no = L"";
1696 nicoLiveChatBase.premium = L"";
1697 nicoLiveChatBase.thread = L"";
1698 nicoLiveChatBase.user_id = L"";
1699 nicoLiveChatBase.vpos = L"";
1700 nicoLiveChatBase.mailCount = 0;
1704 nicoLiveThreadCommentBase.last_res = L"";
1705 nicoLiveThreadCommentBase.thread = L"";
1706 nicoLiveThreadCommentBase.ticket = L"";
1709 nicoLiveSendResultCommentBase.no = L"";
1710 nicoLiveSendResultCommentBase.status = L"";
1711 nicoLiveSendResultCommentBase.thread = L"";
1714 //
\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é
1715 for (;recvBufTmp + strlen(recvBufTmp) < recvEndPoint;recvBufTmp += strlen(recvBufTmp) + 1){
1718 commentSizeCh = sizeof(TCHAR) * GetLenToWide(CP_UTF8,recvBufTmp);
1719 extendMalloc(commentBuf,LPTSTR,*commentBufSize,commentSizeCh);
1720 MBToWide(CP_UTF8,recvBufTmp,commentBuf,*commentBufSize);
1722 traceln(TEXT("comment:\r\n%s"),commentBuf);
1723 //thread
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1724 if((indexPtr = wcsstr(commentBuf,L"<thread ")) != NULL){
1726 indexPtr += wcslen(L"<thread ");
1727 skipXMLSPACE(indexPtr);
1732 nicoLiveThreadComment = nicoLiveThreadCommentBase;
1734 while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1735 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1738 nameLen = attrNameEnd - attrNameStart;
1739 if(wcsncmp(attrNameStart,L"ticket",nameLen) == 0){
1742 partString(nicoLiveThreadComment.ticket,attrValueStart,attrValueEnd);
1743 wcscpy(self->ticket,nicoLiveThreadComment.ticket);
1745 } else if(wcsncmp(attrNameStart,L"last_res",nameLen) == 0){
1747 partString(nicoLiveThreadComment.last_res,attrValueStart,attrValueEnd);
1750 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1752 partString(nicoLiveThreadComment.thread,attrValueStart,attrValueEnd);
1753 } else if(wcsncmp(attrNameStart,L"server_time",nameLen) == 0){
1755 NicoLiveStream_setVpos((*self),attrValueStart);
1757 partString(nicoLiveThreadComment.server_time,attrValueStart,attrValueEnd);
1760 skipXMLSPACE(indexPtr);
1765 self->callBack(NICOLIVE_EVENT_RECEVE_CONNECTRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveThreadComment,self->chatManager.chatNo);
1767 //chat
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1768 } else if((indexPtr = wcsstr(commentBuf,L"<chat ")) != NULL){
1770 indexPtr += wcslen(L"<chat ");
1771 skipXMLSPACE(indexPtr);
1776 nicoLiveChat = nicoLiveChatBase;
1778 while(wcsncmp(indexPtr,L">",wcslen(L">"))){
1780 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1782 nameLen = attrNameEnd - attrNameStart;
1785 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1787 partString(nicoLiveChat.no,attrValueStart,attrValueEnd);
1789 } else if(wcsncmp(attrNameStart,L"date",nameLen) == 0){
1791 NicoLiveStream_setVpos((*self),attrValueStart);
1793 partString(nicoLiveChat.date,attrValueStart,attrValueEnd);
1795 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1797 partString(nicoLiveChat.thread,attrValueStart,attrValueEnd);
1799 } else if(wcsncmp(attrNameStart,L"premium",nameLen) == 0){
1801 partString(nicoLiveChat.premium,attrValueStart,attrValueEnd);
1803 } else if(wcsncmp(attrNameStart,L"anonymity",nameLen) == 0){
1805 partString(nicoLiveChat.anonymity,attrValueStart,attrValueEnd);
1808 } else if(wcsncmp(attrNameStart,L"locale",nameLen) == 0){
1810 partString(nicoLiveChat.locale,attrValueStart,attrValueEnd);
1812 } else if(wcsncmp(attrNameStart,L"vpos",nameLen) == 0){
1814 partString(nicoLiveChat.vpos,attrValueStart,attrValueEnd);
1816 } else if(wcsncmp(attrNameStart,L"user_id",nameLen) == 0){
1818 partString(nicoLiveChat.user_id,attrValueStart,attrValueEnd);
1820 } else if(wcsncmp(attrNameStart,L"name",nameLen) == 0){
1822 partString(nicoLiveChat.name,attrNameStart,attrValueEnd);
1824 } else if(wcsncmp(attrNameStart,L"mail",nameLen) == 0){
1826 nicoLiveChat.mailCount = 1;
1829 for(mailIndexPtr = attrValueStart;mailIndexPtr <= attrValueEnd;mailIndexPtr++){
1831 if(mailIndexPtr[0] == L' '){
1833 nicoLiveChat.mailCount++;
1839 extendMalloc(mailCountBuf,LPTSTR*,*mailCountBufSize,nicoLiveChat.mailCount);
1841 nicoLiveChat.mail = mailCountBuf;
1842 mailCountBuf[0] = NULL;
1844 for(mailIndex = mailCountBuf,mailIndexPtr = attrValueStart,mailIndex[0] = mailIndexPtr;mailIndexPtr < attrValueEnd;mailIndexPtr++){
1847 if(mailIndexPtr[0] == L' '){
1849 mailIndex[0] = mailIndexPtr + 1;
1850 mailIndexPtr[0] = L'\0';
1857 mailIndexPtr[0] = L'\0';
1861 skipXMLSPACE(indexPtr);
1865 xmlTextPtr = indexPtr;
1866 xmlTextEnd = wcsstr(indexPtr,L"<");
1867 convertXMLTEXT(nicoLiveChat.chatBuf,indexPtr,xmlTextPtr,xmlTextEnd);
1871 self->chatManager.chatNo = wcstoul(nicoLiveChat.no,NULL,10);
1875 self->chatManager.commentCountSum++;
1876 isReceveChat = TRUE;
1878 check((_heapchk() == _HEAPOK),TEXT("
\83q
\81[
\83v
\83G
\83\89\81[
\82Å
\82·"));
1880 if((wcscmp(nicoLiveChat.chatBuf,L"/disconnect") == 0 && wcscmp(nicoLiveChat.premium,L"2") == 0)){
1883 _beginthread(NicoLiveSelfDisconnect,0,self);
1885 self->callBack(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&nicoLiveChat,self->chatManager.commentCountSum);
1888 //chat_result
\83m
\81[
\83h
\82Ì
\8fê
\8d\87
1889 } else if((indexPtr = wcsstr(commentBuf,L"<chat_result ")) != NULL){
1891 indexPtr += wcslen(L"<chat_result ");
1893 nicoLiveSendResultComment = nicoLiveSendResultCommentBase;
1895 while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1896 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1899 nameLen = attrNameEnd - attrNameStart;
1900 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1903 partString(nicoLiveSendResultComment.no,attrValueStart,attrValueEnd);
1905 } else if(wcsncmp(attrNameStart,L"status",nameLen) == 0){
1907 partString(nicoLiveSendResultComment.status,attrValueStart,attrValueEnd);
1910 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1912 partString(nicoLiveSendResultComment.thread,attrValueStart,attrValueEnd);
1915 skipXMLSPACE(indexPtr);
1918 //
\83L
\81[
\83v
\83A
\83\89\83C
\83u
\83\8a\83Z
\83b
\83g
1919 WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
1921 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSENDRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveSendResultComment,(NICOLIVE_PARAM)NULL);
1927 if(recvBufTmp == recvEndPoint && isReceveChat){
1928 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSETTLE,self,self->option,self->chatManager.chatNo,self->chatManager.commentCountSum);
1934 strcpy(&self->chatManager.recvBuf[0],recvBufTmp);
1951 static void NicoLiveError(void *buf){
1953 NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1955 nl->callBack(NICOLIVE_EVENT_ERR_CONNECT,nl,nl->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
1957 NicoLiveStream_disConnect(nl);
1965 static void NicoLiveSelfDisconnect(void *buf){
1967 NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1969 dumpln(TEXT("selfdisconnect"),);
1971 NicoLiveStream_disConnect(nl);
1981 static INLINE SOCKET GetConectedSocket(LPCTSTR nordName,LPCTSTR port,int socktype,int addr_famiry,int protocol){
1984 SOCKET rslt = INVALID_SOCKET;
1987 PADDRINFOW res,res0;
1989 ZeroMemory(&hints,sizeof(hints));
1990 hints.ai_socktype = socktype;
1991 hints.ai_family = addr_famiry;
1992 hints.ai_protocol = protocol;
1993 GetAddrInfoW(nordName,port,&hints,&res0);
1996 for(res = res0; res != NULL;res = res->ai_next){
2001 rslt = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
2002 if(rslt == INVALID_SOCKET){
2015 if(connect(rslt,res->ai_addr,(int)res->ai_addrlen) == SOCKET_ERROR){
2030 rslt = INVALID_SOCKET;
2034 //res
\8d\
\91¢
\91Ì
\89ð
\95ú
2044 //
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\8aÖ
\98A
2048 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82ÌID
\82ð
\8eæ
\93¾
2050 NLIB_DECLSPEC LPCTSTR StreamStatus_getId(StreamStatus_P self){
2057 ///
\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¾
2059 NLIB_DECLSPEC LPCTSTR StreamStatus_getDefaultCommunity(StreamStatus_P self){
2061 return self->default_community;
2066 ///
\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¾
2068 PROVIDERTYPE StreamStatus_getProviderType(StreamStatus_P self){
2070 return self->provider_type;
2075 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83I
\81[
\83i
\81[
\83t
\83\89\83O
\82ð
\8eæ
\93¾
2077 BOOL StreamStatus_isOwner(StreamStatus_P self){
2079 return self->is_owner;
2083 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\8aJ
\8en
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2085 time_t StreamStatus_getStartTime(StreamStatus_P self){
2087 return self->start_time;
2091 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\8fI
\97¹
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2093 time_t StreamStatus_getEndTime(StreamStatus_P self){
2095 return self->end_time;
2099 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\8aJ
\8fê
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2101 time_t StreamStatus_getOpenTime(StreamStatus_P self){
2103 return self->open_time;
2108 ///
\83X
\83g
\83\8a\81[
\83\80\83X
\83e
\81[
\83^
\83X
\82Ì
\83x
\81[
\83X
\8e\9e\8d\8f\82ð
\8eæ
\93¾
2110 time_t StreamStatus_getBaseTime(StreamStatus_P self){
2112 return self->base_time;