OSDN Git Service

2012/01/20 14:20:14
[nlite/nlite.git] / nlib / nlib_nicoLive.c
1 #include "StdAfx.h"
2 #include "nlib_include.h"
3
4
5
6
7
8
9 static NicoLiveHeartBeatContainer heartBeatContainer;
10 static CRITICAL_SECTION heartBeatCs;
11
12
13
14 //
15 //\83}\83N\83\8d
16 //
17 #define XMLSPACE L" \t\r\n"
18
19 #define parseAttr(indexPtr,ans,ane,avs,ave)\
20         (ans) = (indexPtr);\
21         (ane) = wcspbrk((ans),XMLSPACE L"=");\
22         (avs) = wcsstr((ane),L"\"") + 1;\
23         (ave) = wcsstr((avs),L"\"");\
24         (indexPtr) = (ave) + 1
25
26 #define skipXMLSPACE(indexPtr)\
27         for(;(*(indexPtr)) == L' ' || (*(indexPtr)) == '\t' || (*(indexPtr)) == '\r' || (*(indexPtr)) == '\n';indexPtr++)
28
29 #define partString(ptr,start,end)\
30         ptr = start;\
31         end[0] = L'\0'
32
33
34 #define convertXMLTEXT(buf,basePtr,convPtr,endPtr)\
35         (buf) = (basePtr);\
36         for(;(basePtr) < (endPtr);(basePtr)++,(convPtr)++){\
37                 if(wcsncmp((basePtr),L"&amp;",wcslen(L"&amp;")) == 0){\
38                         (convPtr)[0] = L'&';\
39                         (basePtr) += wcslen(L"&amp;") - 1;\
40                 } else if(wcsncmp((basePtr),L"&lt;",wcslen(L"&lt;")) == 0){\
41                         (convPtr)[0] = L'<';\
42                         (basePtr) += wcslen(L"&lt;") - 1;\
43                 } else if(wcsncmp((basePtr),L"&gt;",wcslen(L"&gt;")) == 0){\
44                         (convPtr)[0] = L'>';\
45                         (basePtr) += wcslen(L"&gt;") - 1;\
46                 } else if(wcsncmp((basePtr),L"&quot;",wcslen(L"&quot;")) == 0){\
47                         (convPtr)[0] = L'\"';\
48                         (basePtr) += wcslen(L"&quot;") - 1;\
49                 } else if(wcsncmp((basePtr),L"&apos;",wcslen(L"&apos;")) == 0){\
50                         (convPtr)[0] = L'\'';\
51                         (basePtr) += wcslen(L"&apos;") - 1;\
52                 } else {\
53                         (convPtr)[0] = (basePtr)[0];\
54                 }\
55         }\
56         (convPtr)[0] = L'\0'
57
58 #define getBaseVpos(server_time,base_time)      (((server_time) - (base_time)) * 100)
59
60 #define setMsec(mSec)\
61         timeBeginPeriod(1);\
62         (mSec) = timeGetTime();\
63         timeEndPeriod(1)
64
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)
68
69
70
71
72 //
73 //\83v\83\89\83C\83x\81[\83g\8aÖ\90\94
74 //
75
76 ///
77 ///\83v\83\8c\83C\83\84\81[\83X\83e\81[\83^\83X\8eæ\93¾
78 ///
79 static INLINE NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P pPlayerStatus,LPCWSTR userSession,HINTERNET hConnect,LPVOID buffer);
80
81 ///
82 ///nicoLiveHistory\8eæ\93¾
83 ///
84 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect);
85
86
87
88
89
90
91
92
93
94
95
96
97 ///
98 ///\83`\83\83\83b\83g\8eó\90M\83\8b\81[\83v\8aJ\8en\8aÖ\90\94
99 ///
100 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer);
101
102 ///
103 ///\83n\81[\83g\83r\81[\83g\91\97\90M\83\8b\81[\83v\8aÖ\90\94
104 ///
105 static unsigned int WINAPI  NicoLiveHeartBeatThread(void* lpBuffer);
106
107
108 ///
109 ///\83L\81[\83v\83A\83\89\83C\83u\91\97\90M\83\8b\81[\83v\8aÖ\90\94
110 ///
111 static unsigned int WINAPI  NicoLiveKeapALiveThread(void* lpBuffer);
112
113
114
115
116 ///
117 ///\83`\83\83\83b\83g\8eó\90M\83\8b\81[\83v\8aÖ\90\94
118 ///
119 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self);
120
121 ///
122 ///\83\8b\81[\83v
123 ///
124 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend);
125
126 ///
127 ///\83R\83\81\83\93\83g\89ð\90Í\8aÖ\90\94
128 ///
129 static VOID  NicoLiveParseComment(NicoLiveStream_P self,LPWSTR commentBuf,UINT_PTR endSize,LPWSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize);
130
131 static void NicoLiveError(void *buf);
132
133 static void NicoLiveSelfDisconnect(void *buf);
134
135 static VOID OnSendHeartBeat(NicoLiveStream_P self);
136
137 static VOID OnSendKeepAllive(NicoLiveStream_P self);
138 ///
139 ///\83\\83P\83b\83g\8eæ\93¾\8aÖ\90\94
140 ///
141 static INLINE SOCKET GetConectedSocket(LPCWSTR nordName,LPCWSTR port,int socktype,int addr_famiry,int protocol);
142
143
144 StreamStatus_P NicoLiveStream_getStreamStatus(NicoLiveStream_P self){
145
146         return &self->playerStatus.stream;
147 }
148
149 BOOL Initialize_NicoLive(){
150
151
152
153
154
155         //\83n\81[\83g\83r\81[\83g\83R\83\93\83e\83i\8f\89\8aú\89»
156         ZeroMemory(&heartBeatContainer,sizeof(heartBeatContainer));
157         heartBeatContainer.is_restrictSize = sizeof(WCHAR) * LENGTH_1024;
158         heartBeatContainer.is_restrictBuff = (LPWSTR)calloc(1,heartBeatContainer.is_restrictSize);
159         heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
160
161         heartBeatContainer.ticketSize = sizeof(WCHAR) * LENGTH_1024;
162         heartBeatContainer.ticketBuff = (LPWSTR)calloc(1,heartBeatContainer.ticketSize);
163         heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
164
165         InitializeCriticalSection(&heartBeatCs);
166
167
168         return TRUE;
169
170
171
172 }
173
174
175 extern BOOL Finalize_NicoLive(){
176
177
178         DeleteCriticalSection(&heartBeatCs);
179
180         //\83p\81[\83T\8cã\8f\88\97\9d
181         free(heartBeatContainer.is_restrictBuff);
182         free(heartBeatContainer.ticketBuff);
183
184
185         
186
187
188
189
190
191
192         return TRUE;
193 }
194
195
196 NicoLiveStream_P NicoLiveStream_new(){
197         //\90\90¬&\8f\89\8aú\89»
198         NicoLiveStream_P self = (NicoLiveStream_P)calloc(1,sizeof(NicoLiveStream));
199
200         //\8f\89\8aú\92l\82Ì\90Ý\92è
201         self->chatManager.onHeartBeatSend = OnSendHeartBeat;
202
203         self->chatManager.onKeepAlliveSend = OnSendKeepAllive;
204
205         InitializeCriticalSection(&self->sessionManager.cs);
206
207         self->chatManager.heartBeatTime = 300000;
208
209         self->chatManager.heartBeatFlag = TRUE;
210
211         self->chatManager.keepAliveTime = 300000;
212
213         self->chatManager.keapALiveFlag = TRUE;
214
215         self->isConnecting = FALSE;
216
217         self->chatManager.endEvent = WSACreateEvent();
218
219         self->chatManager.startEvent = WSACreateEvent();
220
221         self->chatManager.deleteEvent = WSACreateEvent();
222
223         self->chatManager.setHeartBeatTimeEvent = WSACreateEvent();
224
225         self->chatManager.setKeepAliveTimeEvent = WSACreateEvent();
226
227         self->chatManager.resetEvents[0] = WSACreateEvent();
228
229         self->chatManager.resetEvents[1] = WSACreateEvent();
230
231         self->chatManager.resetEvents[2] = WSACreateEvent();
232
233
234
235
236
237         //\83X\83\8c\83b\83h\82Ì\8aJ\8en
238         self->chatManager.hRecvChatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveRecvChat,self,0,&self->chatManager.recvChatThreadID);
239
240         self->chatManager.hHeartBeatHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveHeartBeatThread,self,0,&self->chatManager.heartBeatThreadID);
241
242         self->chatManager.hKeapALiveHandle = (HANDLE)_beginthreadex(NULL,0,NicoLiveKeapALiveThread,self,0,&self->chatManager.keapALiveThreadID);
243
244
245
246         
247
248         
249
250         dumpln(TEXT("size%d"),sizeof(NicoLiveStream));
251
252         
253
254         return self;
255 }
256
257
258
259 //
260 //\83j\83R\83j\83R\90\95ú\91\97\8aÖ\98A\8aÖ\90\94
261 ///////////////////////////////////////////////////
262
263 VOID NicoLiveStream_delete(NicoLiveStream_P* self){
264
265         NicoLiveStream_disConnect((*self));
266
267         WSASetEvent((*self)->chatManager.deleteEvent);
268
269         if(INVALID_HANDLE_VALUE  != (*self)->chatManager.hRecvChatHandle){
270                 WaitForSingleObject( (*self)->chatManager.hRecvChatHandle, INFINITE );
271                 CloseHandle((*self)->chatManager.hRecvChatHandle);
272         }
273
274         if(INVALID_HANDLE_VALUE != (*self)->chatManager.hHeartBeatHandle){
275
276                 WaitForSingleObject((*self)->chatManager.hHeartBeatHandle,INFINITE);
277                 CloseHandle((*self)->chatManager.hHeartBeatHandle);
278         }
279
280         if(INVALID_HANDLE_VALUE != (*self)->chatManager.hKeapALiveHandle){
281
282                 WaitForSingleObject((*self)->chatManager.hKeapALiveHandle,INFINITE);
283                 CloseHandle((*self)->chatManager.hKeapALiveHandle);
284
285         }
286
287         
288
289         
290
291         
292
293         //\8cã\8f\88\97\9d&\94j\8aü
294
295         DeleteCriticalSection(&(*self)->sessionManager.cs);
296
297         WSACloseEvent((*self)->chatManager.setHeartBeatTimeEvent);
298
299         WSACloseEvent((*self)->chatManager.setKeepAliveTimeEvent);
300
301         WSACloseEvent((*self)->chatManager.endEvent);
302
303         WSACloseEvent((*self)->chatManager.startEvent);
304
305         WSACloseEvent((*self)->chatManager.deleteEvent);
306
307         WSACloseEvent((*self)->chatManager.resetEvents[0]);
308
309         WSACloseEvent((*self)->chatManager.resetEvents[1]);
310
311         WSACloseEvent((*self)->chatManager.resetEvents[2]);
312
313
314
315
316         free((*self));
317
318         (*self) = (NicoLiveStream_P)NULL;
319
320         return;
321 }
322
323
324 ///
325 ///\83n\81[\83g\83r\81[\83g\82Ì\8aÔ\8au\82ð\90Ý\92è\81i\83~\83\8a\95b)
326 ///
327 VOID NicoLiveStream_setHeartBeatMsec(NicoLiveStream_P self,DWORD msec){
328
329         WSASetEvent(self->chatManager.setHeartBeatTimeEvent);
330         self->chatManager.heartBeatTime  = msec;
331         return;
332 }
333
334 ///
335 ///\83n\81[\83g\83r\81[\83g\82Ì\8aÔ\8au\82ð\8eæ\93¾(\83~\83\8a\95b)
336 ///
337 DWORD NicoLiveStream_getHeartBeatMsec(NicoLiveStream_P self){
338
339         return self->chatManager.heartBeatTime;
340
341
342 }
343
344 ///
345 ///\83n\81[\83g\83r\81[\83g\97L\8cø\81E\96³\8cø\90Ý\92è
346 ///
347 VOID NicoLiveStream_setHeartBeatFlag(NicoLiveStream_P self,BOOL flag){
348
349         self->chatManager.heartBeatFlag = flag;
350
351 }
352
353
354 ///
355 ///\83n\81[\83g\83r\81[\83g\97L\8cø\83t\83\89\83O\8eæ\93¾
356 ///
357 BOOL NicoLiveStream_getHeartBeatFlag(NicoLiveStream_P self){
358
359         return self->chatManager.heartBeatFlag;
360
361
362 }
363
364
365 ///
366 ///\83L\81[\83v\83A\83\89\83C\83u\82Ì\8aÔ\8au\82ð\90Ý\92è(\83~\83\8a\95b)
367 ///
368 VOID NicoLiveStream_setKeapALiveMsec(NicoLiveStream_P self,DWORD msec){
369
370         WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
371         self->chatManager.keepAliveTime = msec;
372
373         return;
374
375 }
376
377 ///
378 ///\83L\81[\83v\83A\83\89\83C\83u\82Ì\8aÔ\8au\82ð\8eæ\93¾(\83~\83\8a\95b)
379 ///
380 DWORD NicoLiveStream_getKeapALiveMsec(NicoLiveStream_P self){
381
382         return self->chatManager.keepAliveTime;
383
384 }
385
386
387 ///
388 ///\83L\81[\83v\83A\83\89\83C\83u\97L\8cø\81E\96³\8cø\90Ý\92è
389 ///
390 VOID NicoLiveStream_setKeapALiveFlag(NicoLiveStream_P self,BOOL flag){
391
392         self->chatManager.keapALiveFlag = flag;
393 }
394
395
396 ///
397 ///\83L\81[\83v\83A\83\89\83C\83u\83t\83\89\83O\8eæ\93¾
398 ///
399 BOOL NicoLiveStream_getKeapALiveFlag(NicoLiveStream_P self){
400
401         return self->chatManager.keapALiveFlag;
402
403 }
404
405 VOID NicoLiveStrream_setResFrom(NicoLiveStream_P self,INT_PTR res){
406
407
408
409         self->res_from = (res < 0 || res > 1000) ? 0 : ((-1) * res);
410
411 }
412
413 INT_PTR NicoLiveStream_getResFrom(NicoLiveStream_P self){
414
415         return (-1) * self->res_from;
416 }
417
418 NLIB_RESULT NicoLiveStream_connect(NicoLiveStream_P self,NicoVideoAuth_P nicoVideoAuth,LPCWSTR url,NicoRecvCallBack callback,LPVOID option){
419
420 #define NICOLIVE_CONNECTIONSTREAM_COOKIE_COUNT          1
421 #define LIVENO_LENGTH                                                           LENGTH_NICOLIVEID
422
423         NLIB_RESULT rslt = NLIB_ERR_OK;
424
425
426
427
428
429
430
431         //url\82©\82ç\90Ú\91±\94Ô\8d\86\82ð\92\8a\8fo
432         LPCWSTR pInputLiveNo = url;
433         LPCWSTR psrech = wcsstr(url,L"http://");
434         LPCWSTR pInputLiveNoEnd;
435         WCHAR liveNo[LIVENO_LENGTH] = {0};
436         
437
438         if(self == NULL)goto end;
439
440         //\91O\82É\82Â\82È\82¢\82Å\82¢\82½\95ú\91\97\82ð\90Ø\92f
441         NicoLiveStream_disConnect(self);
442
443         if(psrech != NULL){
444
445                 psrech += 7;
446
447                 for(;psrech != NULL;psrech = wcsstr(psrech +1,L"/")){
448
449                         pInputLiveNo = psrech + 1;
450
451
452                 }
453         }
454
455         pInputLiveNoEnd = wcsstr(pInputLiveNo,L"?");
456
457         if(pInputLiveNoEnd == NULL){
458
459                 pInputLiveNoEnd = pInputLiveNo + wcslen(pInputLiveNo);
460
461         }
462
463         if(pInputLiveNo == NULL){
464
465                 rslt = NLIB_LIVENO_FAILED_INPUT;
466                 goto end;
467
468         }else if(pInputLiveNoEnd - pInputLiveNo + 2 >= LIVENO_LENGTH - 1){
469
470                 rslt = NLIB_LIVENO_FAILED_TOOBIG;
471                 goto end;
472
473         } else if((wcsncmp(pInputLiveNo,TEXT("lv"),2) == 0)||(( wcsncmp(pInputLiveNo,TEXT("co"),2) == 0) || (wcsncmp(pInputLiveNo,TEXT("ch"),2) == 0) )){
474
475
476                 wcsncpy(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
477
478
479         } else if(_wtoi(pInputLiveNo) != 0){
480
481                 wcscpy(liveNo,L"lv");
482                 wcsncat(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
483
484         } else {
485
486                 rslt = NLIB_LIVENO_FAILED_UNDEFEINE;
487                 goto end;
488
489
490         }
491
492
493
494
495         wcsncpy(self->userSession,L"Cookie: ",sizeof(self->userSession) / sizeof(self->userSession[0]) - 1);
496         wcsncat(self->userSession,nicoVideoAuth->userSession,sizeof(self->userSession) / sizeof(self->userSession[0]) - 1);
497         self->userSession[sizeof(self->userSession) / sizeof(self->userSession[0]) - 1] = L'\0';
498
499
500
501
502         {
503                 WCHAR objectName[LENGTH_256] = {L"api/getplayerstatus?v="};
504                 wcsncat(objectName,liveNo,sizeof(objectName) / sizeof(objectName[0]));
505
506
507
508         
509
510                 self->sessionManager.getPlayerStatusSession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
511         }
512
513         //\83v\83\8c\83C\83\84\81[\83X\83e\81[\83^\83X\8eæ\93¾
514         EnterCriticalSection(&self->sessionManager.cs);
515         rslt = GetPlayerStatus(&self->playerStatus,self->userSession,self->sessionManager.getPlayerStatusSession,self->sessionManager.buffer);
516         LeaveCriticalSection(&self->sessionManager.cs);
517
518         if(rslt != NLIB_ERR_OK){
519
520                 goto end;
521         }
522
523
524
525         //\90\95ú\91\97\83I\83u\83W\83F\83N\83g\82É\8ae\88ø\90\94\82ð\90Ý\92è
526
527         self->callBack = callback;
528         self->option = option;
529
530
531         WSASetEvent(self->chatManager.startEvent);
532
533         self->isConnecting = TRUE;
534
535         //nicoLiveHistory\82ð\8eæ\93¾(\95K\97v\82È\82µ\81H)
536         //GetNicoLiveHistory(self,hWatchLiveNicVideo);
537
538 end:
539
540
541         return rslt;
542 }
543
544
545 NLIB_RESULT NicoLiveStream_sendHeartBeat(NicoLiveStream_P self){
546
547         
548         NLIB_RESULT rslt = NLIB_ERR_OK;
549
550         if(self->isConnecting == FALSE){
551                 rslt = NLIB_ERR_NOT_CONNECT;
552                 goto end;
553         }
554         if(self == NULL || self->playerStatus.error != NLIB_ERR_OK){
555
556                 rslt = NLIB_ERR_PLAYERSTATUS_ERROR;
557                 goto end;
558
559         }
560
561
562         EnterCriticalSection(&self->sessionManager.cs);
563         {
564                 //HINTERNET hWatchLiveNicoSession = NULL;
565                 //HINTERNET hGetPlayerStatusRequest = NULL;
566                 const UINT_PTR buflen = LENGTH_65536;
567                 LPVOID buffer = self->sessionManager.buffer;
568          
569                 LPWSTR objectName = (LPWSTR)buffer;
570                 LPWSTR indexPtr;
571                 //LPWSTR sendBuffer = (LPWSTR)&objectName[LENGTH_4096];
572                 LPSTR recvBuffer = (LPSTR)&objectName[LENGTH_4096];
573                 DWORD readSize;
574                 DWORD statusCode;
575                 DWORD statusCodeSize = sizeof(statusCode);
576
577                 //hWatchLiveNicoSession = hWatchLiveNicoConnect;
578
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);
585
586
587
588         
589                 if(self->sessionManager.heartBeatSession == NULL){
590                         self->sessionManager.heartBeatSession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
591                 
592                 }
593                 if(WinHttpSendRequest(self->sessionManager.heartBeatSession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
594
595                         rslt = NLIB_ERR_FAILED_NETWORK;
596                         goto connectend;
597
598                 }
599
600                 if(WinHttpReceiveResponse(self->sessionManager.heartBeatSession,NULL) == FALSE){
601
602                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
603                         goto connectend;
604
605                 }
606
607
608                 if (WinHttpQueryHeaders(self->sessionManager.heartBeatSession,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
609                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
610                         goto connectend;
611                 }
612
613
614                 if (HTTP_STATUS_OK != statusCode){
615                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
616                         goto connectend;
617                 }
618
619
620                 //recvBuffer = (LPSTR)sendBuffer;
621
622
623                 if(ReadHttpBody(self->sessionManager.heartBeatSession,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
624
625                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
626                         goto connectend;
627
628                 }
629
630                 {
631                         
632                         
633                         EnterCriticalSection(&heartBeatCs);
634
635                         XMLParse(&heartBeatContainer,recvBuffer,NicoLiveHeartBeat_ElementStartHandler,NicoLiveHeartBeat_ElementEndHandler,NicoLiveHeartBeat_CharacterDataHandler);
636
637                         self->chatManager.baseVpos = getBaseVpos(heartBeatContainer.heartBeat.time, self->playerStatus.stream.base_time);
638                         setMsec(self->chatManager.commentStartTime);
639
640                         self->callBack(NICOLIVE_EVENT_SEND_HEARTBEAT,self,self->option,(NICOLIVE_PARAM)&heartBeatContainer.heartBeat,(NICOLIVE_PARAM)NULL);
641
642                         ZeroMemory(&heartBeatContainer.heartBeat,sizeof(heartBeatContainer.heartBeat));
643
644                         ZeroMemory(heartBeatContainer.is_restrictBuff,heartBeatContainer.is_restrictSize);
645
646                         ZeroMemory(heartBeatContainer.ticketBuff,heartBeatContainer.ticketSize);
647
648                         heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
649
650                         heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
651
652                         LeaveCriticalSection(&heartBeatCs);
653
654
655                 }
656 connectend:
657                 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
658                 LeaveCriticalSection(&self->sessionManager.cs);
659
660
661                 
662
663         }
664 end:
665         
666
667         return rslt;
668 }
669
670 VOID NicoLiveStream_disConnect(NicoLiveStream_P self){
671
672         if(self == NULL)goto end;
673
674         while(WSAResetEvent(self->chatManager.startEvent) == FALSE);
675         while(WSASetEvent(self->chatManager.endEvent)== FALSE);
676
677         
678
679
680
681         WSAWaitForMultipleEvents(sizeof(self->chatManager.resetEvents) / sizeof(self->chatManager.resetEvents[0]),self->chatManager.resetEvents,TRUE,WSA_INFINITE,FALSE);
682
683
684
685         //nicoLiveStream_Initialize(*self);
686         ZeroMemory(&self->playerStatus,sizeof(self->playerStatus));
687         WSAResetEvent(self->chatManager.endEvent);
688         
689         WinHttpCloseHandle(self->sessionManager.getPlayerStatusSession);
690         self->sessionManager.getPlayerStatusSession = NULL;
691         WinHttpCloseHandle(self->sessionManager.heartBeatSession);
692         self->sessionManager.heartBeatSession = NULL;
693
694
695
696         self->isConnecting = FALSE;
697
698 end:
699
700
701         return;
702
703
704
705 }
706
707
708 #define NICOLIVE_SENDCHATBUFLEN                 LENGTH_4096
709 #define NICOLIVE_SENDFORMAT                             "<chat thread=\"%d\" ticket=\"%S\"  postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
710
711 NLIB_RESULT NicoLiveStream_sendChat(NicoLiveStream_P self,LPCWSTR chatbuf,LPCWSTR *mail,LPCWSTR *extends){
712
713         NLIB_RESULT rslt = NLIB_ERR_OK;
714         EnterCriticalSection(&self->sessionManager.cs);
715         
716         {
717                 const UINT_PTR buflen = LENGTH_65536 * 4;
718                 LPVOID chunk = self->sessionManager.buffer;
719
720                 LPSTR postKey;
721                 LPSTR postKeyBuf = (LPSTR)chunk;
722                 LPWSTR postKeyReqBuf = (LPWSTR)&postKeyBuf[NICOLIVE_SENDCHATBUFLEN];
723                 LPWSTR cookieBuf = &postKeyReqBuf[NICOLIVE_SENDCHATBUFLEN];
724                 DWORD statusCode;
725                 DWORD statusCodeSize = sizeof(statusCode);
726                 DWORD readSize;
727
728                 //HINTERNET hWatchLiveNicoVideo = NULL;
729                 HINTERNET hGetPostKeySession = NULL;
730                 
731
732                 if(self->isConnecting == FALSE){
733                         rslt = NLIB_ERR_NOT_CONNECT;
734                         goto end;
735                 }
736                 if(chatbuf == NULL || wcslen(chatbuf) >= LENGTH_1024){
737
738                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
739                         goto end;
740
741                 }
742
743
744                 //postkey\8eæ\93¾
745                 _swprintf(postKeyReqBuf,L"api/getpostkey?thread=%u&block_no=%u",self->playerStatus.ms.thread,self->chatManager.chatNo / 100);
746
747                 //hWatchLiveNicoVideo = WinHttpConnect(hHttpSession,WTEXT(WATCH_LIVE_NICO_VIDEO_DOMEINNAME),INTERNET_DEFAULT_HTTP_PORT,0);
748                 hGetPostKeySession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",postKeyReqBuf,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
749
750
751                 //_swprintf(cookieBuf,L"Cookie: %s; %s",self->userSession,self->nicoLiveHistory);
752                 _swprintf(cookieBuf,L"Cookie: %s",self->userSession);
753
754                 if(WinHttpSendRequest(hGetPostKeySession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
755
756                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
757                         goto end;
758
759                 }
760
761
762                 if(WinHttpReceiveResponse(hGetPostKeySession,NULL) == FALSE){
763
764                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
765                         goto end;
766
767                 }
768
769
770                 if (WinHttpQueryHeaders(hGetPostKeySession,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
771                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
772                         goto end;
773                 }
774
775
776                 if (HTTP_STATUS_OK != statusCode){
777                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
778                         goto end;
779                 }
780
781
782
783
784
785                 if(ReadHttpBody(hGetPostKeySession,(LPBYTE)postKeyBuf,buflen,&readSize) == FALSE){
786
787                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
788                         goto end;
789
790                 }
791                 postKeyBuf[readSize] = '\0';
792                 postKey = strstr(postKeyBuf,"=") + 1;
793
794
795                 {
796                         LPSTR buffer = (LPSTR)&cookieBuf[NICOLIVE_SENDCHATBUFLEN];
797                         LPSTR indexPtr;
798                         LPSTR mailBuf;
799                         LPSTR extendBuf;
800                 
801                         //mail\83R\83}\83\93\83h\8dì\90¬
802                         if(mail == NULL){
803
804                                 mailBuf = "";
805
806                         } else {
807                                 INT_PTR len;
808                                 mailBuf = (LPSTR)postKeyReqBuf;
809                                 indexPtr = mailBuf;
810                                 strcpy(indexPtr,"mail=\"");
811                                 indexPtr += strlen(indexPtr);
812
813                                 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
814                                 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
815                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
816                                         goto end;
817
818                                 }
819
820                                 WideToMB(CP_UTF8,mail[0],indexPtr,len);
821                                 indexPtr += strlen(indexPtr);
822
823
824                                 for(mail++;mail[0] != NULL;mail++){
825
826                                         indexPtr[0] = ' ';
827                                         indexPtr++;
828
829                                         len =  NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
830
831                                         if(GetLenToMB(CP_UTF8,mail[0]) >= len){
832                                                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
833                                                 goto end;
834
835                                         }
836
837                                         WideToMB(CP_UTF8,mail[0],indexPtr,len);
838                                         indexPtr += strlen(indexPtr);
839
840                                 }
841                                 strcpy(indexPtr,"\"");
842
843
844
845
846                         }
847
848                         //\8ag\92£\91®\90«\8dì\90¬
849                         if(extends == NULL){
850
851                                 extendBuf = "";
852
853                         } else {
854                                 INT_PTR len;
855                                 extendBuf  =(LPSTR)cookieBuf;
856                                 indexPtr = extendBuf;
857
858
859                                 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
860
861                                 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
862                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
863                                         goto end;
864
865                                 }
866                                 WideToMB(CP_UTF8,extends[0],indexPtr,len);
867
868                                 indexPtr += strlen(indexPtr);
869
870                                 strcpy(indexPtr,"=\"");
871                                 indexPtr += strlen(indexPtr);
872
873
874                                 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
875
876                                 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
877                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
878                                         goto end;
879
880                                 }
881                                 WideToMB(CP_UTF8,extends[1],indexPtr,len);
882
883
884                                 for(extends+= 2;extends[0] != NULL;extends+=2){
885
886                                         indexPtr[0] = ' ';
887                                         indexPtr++;
888
889                                         len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
890
891                                         if(GetLenToMB(CP_UTF8,extends[0]) >= len){
892                                                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
893                                                 goto end;
894
895                                         }
896                                         WideToMB(CP_UTF8,extends[0],indexPtr,len);
897
898                                         indexPtr += strlen(indexPtr);
899
900                                         indexPtr[0] = '=';
901                                         indexPtr++;
902
903
904                                         len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
905
906                                         if(GetLenToMB(CP_UTF8,extends[1]) >= len){
907                                                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
908                                                 goto end;
909
910                                         }
911                                         WideToMB(CP_UTF8,extends[1],indexPtr,len);
912
913
914
915                                 }
916                                 indexPtr += strlen(indexPtr);
917                                 strcpy(indexPtr,"\"");
918
919
920
921                         }
922
923                         //\83`\83\83\83b\83g\91\97\90M\83R\83\81\83\93\83g\8dì\90¬
924                         {
925                                 indexPtr = buffer;
926                                 //\96{\93\96\82Í\82±\82¤\82µ\82½\82¢:"<chat thread=\"%d\" ticket=\"%S\"  postkey=\"%s\" user_id=\"%S\" premium=\"%d\" locale=\"%S\" vpos=\"%ld\"%s>%S</chat>"
927                                 strcpy(indexPtr,"<chat thread=\"");
928                                 indexPtr += strlen(indexPtr);
929                                 sprintf(indexPtr,"%u",self->playerStatus.ms.thread);
930                                 indexPtr += strlen(indexPtr);
931                                 strcpy(indexPtr,"\" ticket=\"");
932                                 indexPtr += strlen(indexPtr);
933                                 WideToMB(CP_UTF8,self->ticket,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
934                                 indexPtr += strlen(indexPtr);
935                                 strcpy(indexPtr,"\"  postkey=\"");
936                                 indexPtr += strlen(indexPtr);
937                                 strcpy(indexPtr,postKey);
938                                 indexPtr += strlen(indexPtr);
939                                 strcpy(indexPtr,"\" user_id=\"");
940                                 indexPtr += strlen(indexPtr);
941                                 WideToMB(CP_UTF8,self->playerStatus.user.user_id,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
942                                 indexPtr += strlen(indexPtr);
943                                 strcpy(indexPtr,"\" premium=\"");
944                                 indexPtr += strlen(indexPtr);
945                                 sprintf(indexPtr,"%u",self->playerStatus.user.is_premium);
946                                 indexPtr += strlen(indexPtr);
947                                 strcpy(indexPtr,"\" locale=\"");
948                                 indexPtr += strlen(indexPtr);
949                                 WideToMB(CP_UTF8,self->playerStatus.user.userDomain,indexPtr,NICOLIVE_SENDCHATBUFLEN - (indexPtr - buffer) - 1);
950                                 indexPtr += strlen(indexPtr);
951                                 strcpy(indexPtr,"\" vpos=\"");
952                                 indexPtr += strlen(indexPtr);
953                         
954                         
955                                 timeBeginPeriod(1);
956                                 sprintf(indexPtr,"%u",(self->chatManager.baseVpos + ((timeGetTime() - self->chatManager.commentStartTime) / 10)));
957                                 timeEndPeriod(1);
958                         
959                                 indexPtr += strlen(indexPtr);
960                                 strcpy(indexPtr,"\"");
961                                 indexPtr += strlen(indexPtr);
962
963                                 if(strlen(mailBuf) > 0 && strlen(extendBuf) > 0){
964
965                                         indexPtr[0] = ' ';
966                                         indexPtr++;
967                                         strcpy(indexPtr,mailBuf);
968                                         indexPtr += strlen(indexPtr);
969
970                                         indexPtr[0] = ' ';
971                                         indexPtr++;
972
973                                         strcpy(indexPtr,extendBuf);
974                                         indexPtr += strlen(indexPtr);
975
976
977                                 } else if(strlen(mailBuf) > 0){
978                                         indexPtr[0] = ' ';
979                                         indexPtr++;
980                                         strcpy(indexPtr,mailBuf);
981                                         indexPtr += strlen(indexPtr);
982
983                                 } else if(strlen(extendBuf) > 0){
984                                         indexPtr[0] = ' ';
985                                         indexPtr++;
986                                         strcpy(indexPtr,extendBuf);
987                                         indexPtr += strlen(indexPtr);
988                                 }
989                                 strcpy(indexPtr,">");
990                                 indexPtr += strlen(indexPtr);
991                                 {
992                                         LPWSTR sendBuf = (LPWSTR)&buffer[NICOLIVE_SENDCHATBUFLEN * 4];
993                                         LPWSTR sendPtr = sendBuf;
994                                         LPCWSTR endPtr= chatbuf + wcslen(chatbuf);
995
996
997                                         //convertTEXT(indexPtr,chatbuf,indexPtr,endPtr);
998
999                                         for(;(chatbuf) <= (endPtr);(chatbuf)++){
1000                                                 switch(chatbuf[0]){
1001                                                 case L'&':
1002                                                         wcscpy((sendBuf),L"&amp;");
1003                                                         (sendBuf) += wcslen(sendBuf);
1004                                                         break;
1005                                                 case L'<':
1006                                                         wcscpy((sendBuf),L"&lt;");
1007                                                         (sendBuf) += wcslen(sendBuf);
1008                                                         break;
1009                                                 case L'>':
1010                                                         wcscpy((sendBuf),L"&gt;");
1011                                                         (sendBuf) += wcslen(sendBuf);
1012                                                         break;
1013                                                 case L'\"':
1014                                                         wcscpy((sendBuf),L"&quot;");
1015                                                         (sendBuf) += wcslen(sendBuf);
1016                                                         break;
1017                                                 case L'\'':
1018                                                         wcscpy((sendBuf),L"&apos;");
1019                                                         (sendBuf) += wcslen(sendBuf);
1020                                                         break;
1021                                                 default:
1022                                                         sendBuf[0] = chatbuf[0];
1023                                                         (sendBuf)++;
1024                                                         break;
1025                                                 }
1026                                         }
1027
1028
1029                                         WideToMB(CP_UTF8,sendPtr,indexPtr,NICOLIVE_SENDCHATBUFLEN * 4 - (indexPtr - buffer) - 1);
1030                                         indexPtr += strlen(indexPtr);
1031                                 
1032                                 }
1033                                 strcpy(indexPtr,"</chat>");
1034                                 indexPtr[strlen(indexPtr)] = '\0';
1035
1036
1037
1038                                 {
1039                                         INT_PTR sendLen = 0;
1040                                         INT_PTR sentLen = 0;
1041                                         INT_PTR max = strlen(buffer) + 1;
1042
1043                                         do{
1044                                                 sendLen = send(self->chatManager.sock,buffer,max - sentLen,0);
1045                                                 sentLen += sendLen;
1046                                         } while(sendLen > 0);
1047
1048                                 }
1049                         }
1050                 }
1051
1052                 
1053 end:
1054         
1055         WinHttpCloseHandle(hGetPostKeySession);
1056
1057         ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1058         LeaveCriticalSection(&self->sessionManager.cs);
1059         }
1060
1061
1062
1063         return rslt;
1064
1065 }
1066
1067
1068
1069
1070
1071
1072
1073 //
1074 //\83C\83\93\83\89\83C\83\93\8aÖ\90\94
1075 //
1076
1077
1078
1079 NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P self,LPCWSTR userSession,HINTERNET hConnect,LPVOID buffer){
1080
1081         NLIB_RESULT rslt = NLIB_ERR_OK;
1082
1083         
1084         {
1085                 //HINTERNET hWatchLiveNicoSession = NULL;
1086                 //HINTERNET hGetPlayerStatusRequest = NULL;
1087                 const UINT_PTR buflen = LENGTH_65536;
1088                 //LPVOID buffer = ;
1089                 //LPWSTR sendBuffer;
1090                 LPSTR recvBuffer = (LPSTR)buffer;
1091                 DWORD readSize;
1092                 DWORD statusCode;
1093                 DWORD statusCodeSize = sizeof(statusCode);
1094
1095
1096         
1097
1098                 if(WinHttpSendRequest(hConnect,userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1099
1100                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1101                         goto end;
1102
1103                 }
1104
1105                 if(WinHttpReceiveResponse(hConnect,NULL) == FALSE){
1106
1107                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1108                         goto end;
1109
1110                 }
1111
1112
1113                 if (WinHttpQueryHeaders(hConnect,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1114                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1115                         goto end;
1116                 }
1117
1118
1119                 if (HTTP_STATUS_OK != statusCode){
1120                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1121                         goto end;
1122                 }
1123
1124
1125                 //recvBuffer = (LPSTR)sendBuffer;
1126
1127
1128                 if(ReadHttpBody(hConnect,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
1129
1130                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1131                         goto end;
1132
1133                 }
1134
1135                 recvBuffer[readSize] = '\0';
1136
1137                 recvBuffer = strstr(recvBuffer,"<");
1138
1139                 dumpln_mb(CP_UTF8,"%s",recvBuffer);
1140
1141
1142                 XMLParse(self,recvBuffer,NPlayerStatus_ElementStartHandler,NPlayerStatus_ElementEndHandler,NPlayerStatus_CharacterDataHandler);
1143                 rslt = self->error;
1144                 if(rslt != NLIB_ERR_OK){
1145
1146                         goto end;
1147                 }
1148         }
1149
1150 end:
1151
1152         
1153
1154         
1155
1156         return rslt;
1157
1158 }
1159
1160
1161 #define GETNICOLIVEHIS_OBJNAMELENGTH    LENGTH_256
1162 #define GETNICOLIVEHIS_COOKIELENGTH             LENGTH_512
1163
1164 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect){
1165
1166         NLIB_RESULT rslt = NLIB_ERR_OK;
1167
1168         EnterCriticalSection(&self->sessionManager.cs);
1169         {
1170         //HINTERNET hNicoVideoConnect = NULL;
1171         HINTERNET hStreamBrowse = NULL;
1172
1173
1174         WCHAR objectName[GETNICOLIVEHIS_OBJNAMELENGTH] = {L"/watch/"};
1175         WCHAR cookie[GETNICOLIVEHIS_COOKIELENGTH] = {L"Cookie: "};
1176         DWORD statusCode;
1177         DWORD statusCodeSize = sizeof(statusCode);
1178         DWORD chunkSize = LENGTH_65536;
1179         LPVOID chunkMemory =self->sessionManager.buffer;
1180         
1181
1182
1183         LPWSTR buffer = (LPWSTR)chunkSize;
1184
1185
1186
1187         if((GETNICOLIVEHIS_OBJNAMELENGTH - wcslen(objectName) <= wcslen(self->playerStatus.stream.id)) || GETNICOLIVEHIS_COOKIELENGTH - wcslen(cookie) <= wcslen(self->userSession)){
1188
1189                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1190                 goto end;
1191         } 
1192
1193         wcscat(objectName,self->playerStatus.stream.id);
1194         wcscat(cookie,self->userSession);
1195
1196         
1197
1198         //hNicoVideoConnect = hConnect;
1199
1200         
1201
1202         hStreamBrowse = WinHttpOpenRequest(hNicoVideoConnect,L"GET",objectName,L"1.1",(LPCWSTR)WINHTTP_NO_REFERER,(LPCWSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1203
1204
1205
1206
1207         if(WinHttpSendRequest(hStreamBrowse,cookie,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1208
1209                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1210                 goto end;
1211
1212         }
1213
1214         if(WinHttpReceiveResponse(hStreamBrowse,NULL) == FALSE){
1215
1216                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1217                 goto end;
1218
1219         }
1220
1221         if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,WINHTTP_HEADER_NAME_BY_INDEX,&statusCode,&statusCodeSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1222                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1223                 goto end;
1224         }
1225
1226
1227         if (HTTP_STATUS_OK != statusCode){
1228                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1229                 goto end;
1230         }
1231
1232
1233
1234         if (WinHttpQueryHeaders(hStreamBrowse,WINHTTP_QUERY_SET_COOKIE,WINHTTP_HEADER_NAME_BY_INDEX,buffer,&chunkSize,WINHTTP_NO_HEADER_INDEX) == FALSE){
1235                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1236                 goto end;
1237         }
1238
1239         {
1240                 LPWSTR start =wcsstr(buffer,L"nicolivehistory=");
1241
1242                 LPWSTR end = wcsstr(start,L";");
1243
1244                 UINT_PTR length = end - start;
1245
1246                 if(length >= sizeof(self->nicoLiveHistory)){
1247                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1248                         goto end;
1249
1250                 }
1251
1252                 wcsncpy(self->nicoLiveHistory,start,length);
1253                 self->nicoLiveHistory[length] = L'\0';
1254
1255         }
1256 end:
1257
1258         WinHttpCloseHandle(hStreamBrowse);
1259
1260         }
1261         ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1262         LeaveCriticalSection(&self->sessionManager.cs);
1263
1264
1265         return rslt;
1266
1267
1268
1269 }
1270
1271
1272
1273
1274
1275
1276
1277
1278 static unsigned int WINAPI  NicoLiveKeapALiveThread(void* lpBuffer){
1279
1280         unsigned int rslt = 0;
1281
1282         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1283
1284         rslt = loopCommon(self,self->chatManager.setKeepAliveTimeEvent,self->chatManager.resetEvents[2],self->chatManager.onKeepAlliveSend);
1285
1286         _endthreadex(rslt);
1287
1288         return rslt;
1289 }
1290
1291 static unsigned int WINAPI  NicoLiveHeartBeatThread(void* lpBuffer){
1292
1293         unsigned int rslt = 0;
1294
1295         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1296
1297
1298         rslt = loopCommon(self,self->chatManager.setHeartBeatTimeEvent,self->chatManager.resetEvents[1],self->chatManager.onHeartBeatSend);
1299
1300
1301
1302         _endthreadex(rslt);
1303
1304         return rslt;
1305 }
1306 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend){
1307
1308         unsigned int rslt = 0;
1309         WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent};   //\83C\83x\83\93\83g\94z\97ñ
1310         WSAEVENT streamEvent[2] = {self->chatManager.endEvent,sendEvent};
1311         DWORD dwResult;                                                                                                                                                                                                 //\83C\83x\83\93\83g\8eó\90M\8c\8b\89Ê
1312         DWORD endResult;
1313
1314         while(TRUE){
1315 restart:
1316                 WSASetEvent(resetEvent);
1317                 
1318                 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1319
1320
1321                 //\83G\83\89\81[\82Ì\8fê\8d\87
1322                 if(dwResult == WSA_WAIT_FAILED){
1323
1324                         goto err;
1325                 }
1326
1327
1328                 switch(dwResult - WSA_WAIT_EVENT_0){
1329
1330                 case 0:
1331
1332                         goto end;
1333
1334                 case 1:
1335                         WSAResetEvent(resetEvent);
1336                         break;
1337
1338                 case 2:
1339                         continue;
1340
1341
1342                 default:
1343
1344                         goto err;
1345
1346                 }
1347
1348                 while(TRUE){
1349                         WSAResetEvent(sendEvent);
1350                         endResult = WSAWaitForMultipleEvents(sizeof(streamEvent) / sizeof(streamEvent[0]),streamEvent,FALSE,self->chatManager.heartBeatTime,FALSE);
1351
1352                         if(endResult == WSA_WAIT_TIMEOUT){
1353
1354                                 nicoLiveOnSend(self);
1355                                 //dumpln(TEXT("onSend"));
1356
1357                                 _heapmin();
1358                         } else{ 
1359                                 switch(endResult - WSA_WAIT_EVENT_0){
1360
1361                                 case 0:
1362                                         goto restart;
1363
1364                                 case 1:
1365                                         break;
1366
1367                                 default:
1368                                         goto err;
1369                                 }
1370                         } 
1371                 }
1372
1373
1374
1375
1376         }
1377
1378 end:
1379         return rslt;
1380
1381 err:
1382         _beginthread(NicoLiveError,0,self);
1383         rslt = 1;
1384         goto end;
1385 }
1386
1387 static VOID OnSendHeartBeat(NicoLiveStream_P self){
1388
1389         if(self->chatManager.heartBeatFlag){
1390                 NicoLiveStream_sendHeartBeat(self);
1391         }
1392
1393 }
1394
1395 static VOID OnSendKeepAllive(NicoLiveStream_P self){
1396         
1397         if(self->chatManager.keapALiveFlag){
1398                 LPCWSTR mail[2] = {L"184",NULL};
1399                 NicoLiveStream_sendChat(self,L"/keapalive",mail,NULL);
1400         }
1401
1402 }
1403
1404 #define NICOLIVE_RECEVE_CHAT_LENGTH     LENGTH_2048
1405 #define NICOLIVE_REQUEST_CHAT_LENGTH    LENGTH_256
1406 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer){
1407
1408
1409         unsigned int rslt = 0;
1410
1411         //LPWSTR user_id = NULL;
1412         //LPWSTR name = NULL;
1413         //LPWSTR chatBuf = NULL;
1414
1415
1416
1417         CHAR requestChat[NICOLIVE_REQUEST_CHAT_LENGTH];                                                                                                                                 //\91\97\90M\93d\95\97p\83o\83b\83t\83@
1418         LPCSTR sendFormat = "<thread thread=\"%u\" res_from=\"%d\" version=\"20061206\" />";                                                    //\91\97\90M\93d\95\83t\83H\81[\83}\83b\83g
1419         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;                                                                                                                             //\83j\83R\90\95ú\91\97\83I\83u\83W\83F\83N\83g
1420         INT_PTR sendLen;                                                                                                                                                                                                //\91\97\90M\97p\95\8e\9a\90\94
1421         INT_PTR sentLen;                                                                                                                                                                                                //\91\97\90M\8dÏ\82Ý\95\8e\9a\90\94
1422         WSAEVENT events[3] = {self->chatManager.deleteEvent,self->chatManager.startEvent,self->chatManager.endEvent};   //\83C\83x\83\93\83g\94z\97ñ
1423         DWORD dwResult;                                                                                                                                                                                                 //\83C\83x\83\93\83g\8eó\90M\8c\8b\89Ê
1424
1425         
1426
1427         while(TRUE){
1428
1429                 WSASetEvent(self->chatManager.resetEvents[0]);
1430
1431                 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1432
1433
1434                 //\83G\83\89\81[\82Ì\8fê\8d\87
1435                 if(dwResult == WSA_WAIT_FAILED){
1436
1437                         goto err;
1438                 }
1439
1440
1441                 switch(dwResult - WSA_WAIT_EVENT_0){
1442
1443                 case 0:
1444
1445                         goto end;
1446
1447                 case 1:
1448                         WSAResetEvent(self->chatManager.resetEvents[0]);
1449                         break;
1450
1451                 case 2:
1452                         continue;
1453
1454                 default:
1455
1456                         goto err;
1457
1458                 }
1459
1460
1461                 sendLen = 0;
1462                 sentLen = 0;
1463
1464                 //\83\\83P\83b\83g\82Ì\90Ý\92è
1465                 self->chatManager.sock = GetConectedSocket(self->playerStatus.ms.addr,self->playerStatus.ms.port,SOCK_STREAM,AF_INET,IPPROTO_TCP);
1466
1467
1468                 //\83R\83\81\83\93\83g\8eó\90M\8aJ\8en\82Ì\89º\8f\80\94õ
1469                 if(self->chatManager.sock == INVALID_SOCKET){
1470                         self->error = NLIB_ERR_FAILED_NETWORK;
1471                         goto err;
1472                 }
1473
1474
1475
1476
1477
1478
1479                 if(NICOLIVE_REQUEST_CHAT_LENGTH <= _scprintf(sendFormat,self->playerStatus.ms.thread,self->res_from)){
1480
1481                         self->error = NLIB_ERR_BUFFER_TOOLITTLE;
1482                         rslt = -1;
1483                         goto err;
1484
1485
1486                 }
1487
1488                 sprintf(requestChat,sendFormat,self->playerStatus.ms.thread,self->res_from);
1489
1490
1491                 //
1492                 //\83R\83\81\83\93\83g\8eó\90M\97v\8b\81\91\97\90M\8f\88\97\9d
1493                 //
1494                 {
1495                         int len;
1496                         sendLen = strlen(requestChat) + 1;
1497                         do{
1498                                 len = send(self->chatManager.sock,requestChat,sendLen,0);
1499                                 if(len == SOCKET_ERROR){
1500                                         self->error = NLIB_ERR_FAILED_NETWORK;
1501                                         rslt = -1;
1502
1503                                         goto err;
1504
1505                                 }
1506
1507                                 sentLen = len;
1508                         }while(sentLen < sendLen);
1509                 }
1510
1511
1512                 if(NicoLiveRecvChatLoop(self) == FALSE){
1513                         goto err;
1514                 }
1515
1516                 
1517         }
1518
1519
1520
1521
1522 err:
1523
1524         _beginthread(NicoLiveError,0,self);
1525
1526 end:
1527
1528
1529
1530         closesocket(self->chatManager.sock);
1531         _endthreadex(rslt);
1532
1533         return rslt;
1534
1535
1536
1537
1538
1539 }
1540
1541
1542
1543
1544
1545 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self){
1546
1547
1548         //
1549         //\83R\83\81\83\93\83g\8eó\90M\8f\88\97\9d
1550         //
1551         BOOL rslt = TRUE;                                                                               //\8c\8b\89Ê
1552         LPWSTR commentBuf = NULL;                                                               //\83R\83\81\83\93\83g\83o\83b\83t\83@
1553         LPWSTR* mailCountBuf = NULL;                                                    //\83\81\81[\83\8b\83|\83C\83\93\83^\83o\83b\83t\83@
1554         INT_PTR recevedLen;                                                                             //\8eó\90M\95\8e\9a\97ñ\92·
1555         INT_PTR messageBufLen;                                                                  //\83o\83b\83t\83@\92·
1556
1557
1558
1559         WSAEVENT hEventArray[2];                                                                //\8eó\90M\81E\90Ø\92f\82ð\8c\9f\92m\82·\82é\83C\83x\83\93\83g\83I\83u\83W\83F\83N\83g\82Ì\94z\97ñ
1560         WSANETWORKEVENTS netEvents;                                                             //\83l\83b\83g\83\8f\81[\83N\83C\83x\83\93\83g
1561         DWORD dwResult;                                                                                 //\83C\83x\83\93\83g\82ª\83E\83F\83C\83g\8aÖ\90\94\82Ì\8c\8b\89Ê\82ð\8ai\94[\82·\82é\95Ï\90\94
1562
1563         
1564         SIZE_T commentBufSize = sizeof(WCHAR) * LENGTH_2048;    //\83R\83\81\83\93\83g\83o\83b\83t\83@\92·
1565         SIZE_T mailCountBufSize = sizeof(LPWSTR) * LENGTH_256;  //\83\81\81[\83\8b\82Ì\83|\83C\83\93\83^\97p\83o\83b\83t\83@\92·
1566
1567
1568         WSAEVENT hRecvEvent = NULL;
1569
1570         //\8eó\90M\8f\80\94õ\8f\88\97\9d
1571         self->chatManager.commentCountSum = 0;
1572         hRecvEvent = WSACreateEvent();
1573         self->chatManager.recvBuf[0] = '\0';
1574         WSAEventSelect(self->chatManager.sock, hRecvEvent, FD_READ | FD_CLOSE);
1575         hEventArray[0] = hRecvEvent;
1576         hEventArray[1] = self->chatManager.endEvent;
1577
1578         commentBuf = (LPWSTR)malloc(commentBufSize);
1579         mailCountBuf = (LPWSTR*)malloc(mailCountBufSize);
1580
1581         //\90Ø\92f\82³\82ê\82é\82Ü\82Å\83\8b\81[\83v
1582         while(1){
1583
1584
1585
1586                 //\91O\82Ì\83R\83\81\83\93\83g\8eó\90M\8e\9e\82É\97]\82Á\82½\95\8e\9a\97ñ\82Ì\92·\82³\82ð\92²\82×\82é
1587                 messageBufLen = strlen(self->chatManager.recvBuf);
1588
1589                 //\8eó\90M\82©\8fI\97¹\83C\83x\83\93\83g\82ð\8c\9f\92m\82·\82é\82Ü\82Å\91Ò\8b@
1590                 dwResult = WSAWaitForMultipleEvents(sizeof(hEventArray) / sizeof(hEventArray[0]),hEventArray,FALSE,WSA_INFINITE,FALSE);
1591
1592                 //\83G\83\89\81[\82Ì\8fê\8d\87
1593                 if(dwResult == WSA_WAIT_FAILED){
1594
1595                         goto err;
1596                 }
1597
1598
1599
1600                 //\83R\83\81\83\93\83g\8eó\90M\83C\83x\83\93\83g\82ª\83V\83O\83i\83\8b\82É\82È\82Á\82½\8fê\8d\87
1601                 if(dwResult - WSA_WAIT_EVENT_0 == 0){
1602
1603                         WSAEnumNetworkEvents(self->chatManager.sock,hRecvEvent,&netEvents);
1604
1605                         //\93Ç\8eæ\83C\83x\83\93\83g\82Ì\8fê\8d\87\83R\83\81\83\93\83g\82ð\8eó\90M\82·\82é
1606                         if(netEvents.lNetworkEvents & FD_READ){
1607
1608
1609                                 recevedLen = recv(self->chatManager.sock,&self->chatManager.recvBuf[messageBufLen],(sizeof(self->chatManager.recvBuf) - 1) - messageBufLen ,0);
1610
1611                                 if(recevedLen == SOCKET_ERROR){
1612                                         self->error = NLIB_ERR_FAILED_NETWORK;
1613
1614                                         goto err;
1615                                 }
1616
1617                                 self->chatManager.recvBuf[messageBufLen + recevedLen] = '\0';
1618
1619
1620
1621
1622
1623
1624                                 NicoLiveParseComment(self,commentBuf,messageBufLen + recevedLen,mailCountBuf,&mailCountBufSize,&commentBufSize);
1625
1626
1627
1628
1629
1630                         } else if(netEvents.lNetworkEvents && FD_CLOSE){
1631
1632                                 goto end;
1633
1634                         }//if(netEvents.lNetworkEvents & FD_READ)
1635
1636                 } else if(dwResult - WSA_WAIT_EVENT_0 == 1){
1637
1638                         goto end;
1639
1640                 }//if(dwResult - WSA_WAIT_EVENT_0 == 0)
1641         }
1642
1643
1644 err:
1645
1646         rslt = FALSE;
1647
1648 end:
1649
1650         free(commentBuf);
1651         free(mailCountBuf);
1652         WSACloseEvent(hRecvEvent);
1653
1654         return rslt;
1655 }
1656
1657
1658
1659
1660 static VOID  NicoLiveParseComment(NicoLiveStream_P self,LPWSTR commentBuf,UINT_PTR endSize,LPWSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize){
1661
1662         LPWSTR indexPtr;                                                                                //\89ð\90Í\8e\9e\82Ì\8ew\95W\83|\83C\83\93\83^
1663         NicoLiveChat nicoLiveChat;                                                              //\83`\83\83\83b\83g\83R\83\81\83\93\83g\8ai\94[\97p\8d\\91¢\91Ì
1664         NicoLiveThreadComment nicoLiveThreadComment;                    //\90Ú\91±\89\9e\93\9a\83R\83\81\83\93\83g\8ai\94[\97p\8d\\91¢\91Ì
1665         NicoLiveSendResultComment nicoLiveSendResultComment;    //\91\97\90M\89\9e\93\9a\83R\83\81\83\93\83g\8ai\94[\97p\8d\\91¢\91Ì
1666         NicoLiveChat nicoLiveChatBase;                                                  //\83`\83\83\83b\83g\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì
1667         NicoLiveThreadComment nicoLiveThreadCommentBase;                //\90Ú\91±\89\9e\93\9a\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì
1668         NicoLiveSendResultComment nicoLiveSendResultCommentBase;//\91\97\90M\89\9e\93\9a\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì
1669         LPWSTR attrNameStart;                                                                   //\91®\90«\96¼\8aJ\8en\83|\83C\83\93\83^
1670         LPWSTR attrNameEnd;                                                                             //\91®\90«\96¼\8fI\97¹\83|\83C\83\93\83^
1671         LPWSTR attrValueStart;                                                                  //\91®\90«\92l\8aJ\8en\83|\83C\83\93\83^
1672         LPWSTR attrValueEnd;                                                                    //\91®\90«\92l\8fI\97¹\83|\83C\83\93\83^
1673         INT_PTR nameLen;                                                                                //\91®\90«\82Ì\96¼\91O\82Ì\92·\82³
1674         LPWSTR mailIndexPtr;                                                                    //\83\81\81[\83\8b\91®\90«\92l\89ð\90Í\97p\8ew\95W\83|\83C\83\93\83^
1675         LPWSTR xmlTextPtr;                                                                              //xml\83e\83L\83X\83g\8c`\8e®\82Ì\83f\81[\83^\89ð\90Í\8e\9e\82É\8eg\97p\82·\82é\83|\83C\83\93\83^
1676         LPWSTR xmlTextEnd;                                                                              //xml\83e\83L\83X\83g\8fI\97¹\83|\83C\83\93\83^
1677         LPWSTR* mailIndex;                                                                              //\83\81\81[\83\8b\83R\83}\83\93\83h\83\8a\83X\83g\83|\83C\83\93\83^
1678         BOOL isReceveChat = FALSE;                                                              //\83`\83\83\83b\83g\8eó\90M\83t\83\89\83O
1679         SIZE_T commentSizeCh;                                                                   //\8eó\90M\82µ\82½\83R\83\81\83\93\83g\82ð\83\86\83j\83R\81[\83h\82É\95Ï\8a·\82·\82é\82Æ\82«\82Ì\92·\82³
1680         LPSTR recvBufTmp;                                                                               //\8eó\90M\95\8e\9a\97ñ\91\80\8dì\97p\83|\83C\83\93\83^
1681         LPSTR recvEndPoint;                                                                             //\8eó\90M\95\8e\9a\97ñ\8fI\92[\83|\83C\83\93\83^
1682
1683
1684
1685         recvBufTmp = &self->chatManager.recvBuf[0];
1686         recvEndPoint = &self->chatManager.recvBuf[endSize];
1687
1688
1689         //\83R\83\81\83\93\83g\8aî\92ê\8d\\91¢\91Ì\8f\89\8aú\89»
1690         nicoLiveChatBase.anonymity = L"";
1691         nicoLiveChatBase.chatBuf = L"";
1692         nicoLiveChatBase.date = L"";
1693         nicoLiveChatBase.locale = L"";
1694         nicoLiveChatBase.mail = mailCountBuf;
1695         nicoLiveChatBase.name = L"";
1696         nicoLiveChatBase.no = L"";
1697         nicoLiveChatBase.premium = L"";
1698         nicoLiveChatBase.thread = L"";
1699         nicoLiveChatBase.user_id = L"";
1700         nicoLiveChatBase.vpos = L"";
1701         nicoLiveChatBase.mailCount = 0;
1702
1703
1704
1705         nicoLiveThreadCommentBase.last_res = L"";
1706         nicoLiveThreadCommentBase.thread = L"";
1707         nicoLiveThreadCommentBase.ticket = L"";
1708
1709
1710         nicoLiveSendResultCommentBase.no = L"";
1711         nicoLiveSendResultCommentBase.status = L"";
1712         nicoLiveSendResultCommentBase.thread = L"";
1713
1714         
1715         //\8eó\90M\82µ\82½\83R\83\81\83\93\83g\82ð\82Ð\82Æ\82Â\82Ìxml\83m\81[\83h\82²\82Æ\82É\89ð\90Í\82·\82é
1716         for (;recvBufTmp + strlen(recvBufTmp) < recvEndPoint;recvBufTmp += strlen(recvBufTmp) + 1){
1717
1718
1719                 commentSizeCh = sizeof(WCHAR) * GetLenToWide(CP_UTF8,recvBufTmp);
1720                 extendMalloc(commentBuf,LPWSTR,*commentBufSize,commentSizeCh);
1721                 MBToWide(CP_UTF8,recvBufTmp,commentBuf,*commentBufSize);
1722
1723                 traceln(TEXT("comment:\r\n%s"),commentBuf);
1724                 //thread\83m\81[\83h\82Ì\8fê\8d\87
1725                 if((indexPtr = wcsstr(commentBuf,L"<thread ")) != NULL){
1726
1727                         indexPtr += wcslen(L"<thread ");
1728                         skipXMLSPACE(indexPtr);
1729
1730
1731
1732
1733                         nicoLiveThreadComment = nicoLiveThreadCommentBase;
1734
1735                         while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1736                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1737
1738
1739                                 nameLen = attrNameEnd - attrNameStart;
1740                                 if(wcsncmp(attrNameStart,L"ticket",nameLen) == 0){
1741
1742
1743                                         partString(nicoLiveThreadComment.ticket,attrValueStart,attrValueEnd);
1744                                         wcscpy(self->ticket,nicoLiveThreadComment.ticket);
1745
1746                                 } else if(wcsncmp(attrNameStart,L"last_res",nameLen) == 0){
1747
1748                                         partString(nicoLiveThreadComment.last_res,attrValueStart,attrValueEnd);
1749
1750
1751                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1752
1753                                         partString(nicoLiveThreadComment.thread,attrValueStart,attrValueEnd);
1754                                 } else if(wcsncmp(attrNameStart,L"server_time",nameLen) == 0){
1755
1756                                         NicoLiveStream_setVpos((*self),attrValueStart);
1757
1758                                         partString(nicoLiveThreadComment.server_time,attrValueStart,attrValueEnd);
1759                                 }
1760
1761                                 skipXMLSPACE(indexPtr);
1762                         }
1763
1764                         
1765
1766                         self->callBack(NICOLIVE_EVENT_RECEVE_CONNECTRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveThreadComment,self->chatManager.chatNo);
1767
1768                         //chat\83m\81[\83h\82Ì\8fê\8d\87
1769                 } else if((indexPtr = wcsstr(commentBuf,L"<chat ")) != NULL){
1770
1771                         indexPtr += wcslen(L"<chat ");
1772                         skipXMLSPACE(indexPtr);
1773
1774
1775
1776                         
1777                         nicoLiveChat = nicoLiveChatBase;
1778
1779                         while(wcsncmp(indexPtr,L">",wcslen(L">"))){
1780
1781                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1782
1783                                 nameLen = attrNameEnd - attrNameStart;
1784
1785
1786                                 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1787
1788                                         partString(nicoLiveChat.no,attrValueStart,attrValueEnd);
1789
1790                                 } else if(wcsncmp(attrNameStart,L"date",nameLen) == 0){
1791
1792                                         NicoLiveStream_setVpos((*self),attrValueStart);
1793
1794                                         partString(nicoLiveChat.date,attrValueStart,attrValueEnd);
1795
1796                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1797
1798                                         partString(nicoLiveChat.thread,attrValueStart,attrValueEnd);
1799
1800                                 } else if(wcsncmp(attrNameStart,L"premium",nameLen) == 0){
1801
1802                                         partString(nicoLiveChat.premium,attrValueStart,attrValueEnd);
1803
1804                                 }  else if(wcsncmp(attrNameStart,L"anonymity",nameLen) == 0){
1805
1806                                         partString(nicoLiveChat.anonymity,attrValueStart,attrValueEnd);
1807
1808
1809                                 } else if(wcsncmp(attrNameStart,L"locale",nameLen) == 0){
1810
1811                                         partString(nicoLiveChat.locale,attrValueStart,attrValueEnd);
1812
1813                                 } else if(wcsncmp(attrNameStart,L"vpos",nameLen) == 0){
1814
1815                                         partString(nicoLiveChat.vpos,attrValueStart,attrValueEnd);
1816
1817                                 } else if(wcsncmp(attrNameStart,L"user_id",nameLen) == 0){
1818
1819                                         partString(nicoLiveChat.user_id,attrValueStart,attrValueEnd);
1820
1821                                 } else if(wcsncmp(attrNameStart,L"name",nameLen) == 0){
1822
1823                                         partString(nicoLiveChat.name,attrNameStart,attrValueEnd);
1824
1825                                 } else if(wcsncmp(attrNameStart,L"mail",nameLen) == 0){
1826
1827                                         nicoLiveChat.mailCount = 1;
1828
1829
1830                                         for(mailIndexPtr = attrValueStart;mailIndexPtr <= attrValueEnd;mailIndexPtr++){
1831
1832                                                 if(mailIndexPtr[0] == L' '){
1833
1834                                                         nicoLiveChat.mailCount++;
1835
1836                                                 }
1837
1838                                         }
1839
1840                                         extendMalloc(mailCountBuf,LPWSTR*,*mailCountBufSize,nicoLiveChat.mailCount);
1841
1842                                         nicoLiveChat.mail = mailCountBuf;
1843                                         mailCountBuf[0] = NULL;
1844
1845                                         for(mailIndex = mailCountBuf,mailIndexPtr = attrValueStart,mailIndex[0] = mailIndexPtr;mailIndexPtr < attrValueEnd;mailIndexPtr++){
1846
1847
1848                                                 if(mailIndexPtr[0] == L' '){
1849                                                         mailIndex++;
1850                                                         mailIndex[0] = mailIndexPtr + 1;
1851                                                         mailIndexPtr[0] = L'\0';
1852
1853
1854                                                 }
1855
1856                                         }
1857
1858                                         mailIndexPtr[0] = L'\0';
1859
1860                                 }
1861
1862                                 skipXMLSPACE(indexPtr);
1863                         }
1864
1865                         indexPtr++;
1866                         xmlTextPtr = indexPtr;
1867                         xmlTextEnd = wcsstr(indexPtr,L"<");
1868                         convertXMLTEXT(nicoLiveChat.chatBuf,indexPtr,xmlTextPtr,xmlTextEnd);
1869
1870
1871
1872                         self->chatManager.chatNo =  wcstoul(nicoLiveChat.no,NULL,10);
1873
1874
1875                         
1876                         self->chatManager.commentCountSum++;
1877                         isReceveChat = TRUE;
1878
1879                         check((_heapchk() == _HEAPOK),TEXT("\83q\81[\83v\83G\83\89\81[\82Å\82·"));
1880
1881                         if((wcscmp(nicoLiveChat.chatBuf,L"/disconnect") == 0 && wcscmp(nicoLiveChat.premium,L"2") == 0)){
1882
1883                                 
1884                                 _beginthread(NicoLiveSelfDisconnect,0,self);
1885                         }
1886                         self->callBack(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&nicoLiveChat,self->chatManager.commentCountSum);
1887                         
1888
1889                         //chat_result\83m\81[\83h\82Ì\8fê\8d\87
1890                 } else if((indexPtr = wcsstr(commentBuf,L"<chat_result ")) != NULL){
1891
1892                         indexPtr += wcslen(L"<chat_result ");
1893
1894                         nicoLiveSendResultComment = nicoLiveSendResultCommentBase;
1895
1896                         while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1897                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1898
1899
1900                                 nameLen = attrNameEnd - attrNameStart;
1901                                 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1902
1903
1904                                         partString(nicoLiveSendResultComment.no,attrValueStart,attrValueEnd);
1905
1906                                 } else if(wcsncmp(attrNameStart,L"status",nameLen) == 0){
1907
1908                                         partString(nicoLiveSendResultComment.status,attrValueStart,attrValueEnd);
1909
1910
1911                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1912
1913                                         partString(nicoLiveSendResultComment.thread,attrValueStart,attrValueEnd);
1914                                 }
1915
1916                                 skipXMLSPACE(indexPtr);
1917                         }
1918
1919                         //\83L\81[\83v\83A\83\89\83C\83u\83\8a\83Z\83b\83g
1920                         WSAResetEvent(self->chatManager.setKeepAliveTimeEvent);
1921
1922                         self->callBack(NICOLIVE_EVENT_RECEVE_CHATSENDRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveSendResultComment,(NICOLIVE_PARAM)NULL);
1923
1924                 }
1925
1926         }
1927
1928         if(recvBufTmp == recvEndPoint && isReceveChat){
1929                 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSETTLE,self,self->option,self->chatManager.chatNo,self->chatManager.commentCountSum);
1930         }
1931
1932
1933
1934
1935         strcpy(&self->chatManager.recvBuf[0],recvBufTmp);
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946         return;
1947
1948 }
1949
1950
1951
1952 static void NicoLiveError(void *buf){
1953
1954         NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1955
1956         nl->callBack(NICOLIVE_EVENT_ERR_CONNECT,nl,nl->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
1957
1958         NicoLiveStream_disConnect(nl);
1959
1960
1961         _endthread();
1962         return;
1963
1964 }
1965
1966 static void NicoLiveSelfDisconnect(void *buf){
1967
1968         NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1969
1970         dumpln(TEXT("selfdisconnect"),);
1971
1972         NicoLiveStream_disConnect(nl);
1973
1974         _heapmin();
1975
1976
1977         _endthread();
1978         return;
1979
1980 }
1981
1982 static INLINE SOCKET GetConectedSocket(LPCWSTR nordName,LPCWSTR port,int socktype,int addr_famiry,int protocol){
1983
1984
1985         SOCKET rslt = INVALID_SOCKET;
1986
1987
1988         PADDRINFOW res,res0;
1989         ADDRINFOW hints;
1990         ZeroMemory(&hints,sizeof(hints));
1991         hints.ai_socktype = socktype;
1992         hints.ai_family = addr_famiry;
1993         hints.ai_protocol = protocol;
1994         GetAddrInfoW(nordName,port,&hints,&res0);
1995
1996
1997         for(res = res0; res != NULL;res = res->ai_next){
1998
1999
2000
2001
2002                 rslt = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
2003                 if(rslt == INVALID_SOCKET){
2004
2005                         continue;
2006                 }
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016                 if(connect(rslt,res->ai_addr,(int)res->ai_addrlen) == SOCKET_ERROR){
2017                         closesocket(rslt);
2018                         continue;
2019                 }
2020
2021
2022
2023
2024
2025
2026                 break;
2027
2028         }
2029
2030         if(res == NULL){
2031                 rslt = INVALID_SOCKET;
2032         }
2033
2034
2035         //res\8d\\91¢\91Ì\89ð\95ú
2036         FreeAddrInfo(res0);
2037
2038
2039         return rslt;
2040
2041 }