OSDN Git Service

2012/01/23 17:17:27
[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,LPCTSTR 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,LPDWORD time);
125
126 ///
127 ///\83R\83\81\83\93\83g\89ð\90Í\8aÖ\90\94
128 ///
129 static VOID  NicoLiveParseComment(NicoLiveStream_P self,LPTSTR commentBuf,UINT_PTR endSize,LPTSTR* 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(LPCTSTR nordName,LPCTSTR 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(TCHAR) * LENGTH_1024;
158         heartBeatContainer.is_restrictBuff = (LPTSTR)calloc(1,heartBeatContainer.is_restrictSize);
159         heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
160
161         heartBeatContainer.ticketSize = sizeof(TCHAR) * LENGTH_1024;
162         heartBeatContainer.ticketBuff = (LPTSTR)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 = FALSE;
210
211         self->chatManager.keepAliveTime = 900000;
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         return self;
246 }
247
248
249
250 //
251 //\83j\83R\83j\83R\90\95ú\91\97\8aÖ\98A\8aÖ\90\94
252 ///////////////////////////////////////////////////
253
254 VOID NicoLiveStream_delete(NicoLiveStream_P* self){
255
256         NicoLiveStream_disConnect((*self));
257
258         WSASetEvent((*self)->chatManager.deleteEvent);
259
260         if(INVALID_HANDLE_VALUE  != (*self)->chatManager.hRecvChatHandle){
261                 WaitForSingleObject( (*self)->chatManager.hRecvChatHandle, INFINITE );
262                 CloseHandle((*self)->chatManager.hRecvChatHandle);
263         }
264
265         if(INVALID_HANDLE_VALUE != (*self)->chatManager.hHeartBeatHandle){
266
267                 WaitForSingleObject((*self)->chatManager.hHeartBeatHandle,INFINITE);
268                 CloseHandle((*self)->chatManager.hHeartBeatHandle);
269         }
270
271         if(INVALID_HANDLE_VALUE != (*self)->chatManager.hKeapALiveHandle){
272
273                 WaitForSingleObject((*self)->chatManager.hKeapALiveHandle,INFINITE);
274                 CloseHandle((*self)->chatManager.hKeapALiveHandle);
275
276         }
277
278         
279
280         
281
282         
283
284         //\8cã\8f\88\97\9d&\94j\8aü
285
286         DeleteCriticalSection(&(*self)->sessionManager.cs);
287
288         WSACloseEvent((*self)->chatManager.setHeartBeatTimeEvent);
289
290         WSACloseEvent((*self)->chatManager.setKeepAliveTimeEvent);
291
292         WSACloseEvent((*self)->chatManager.endEvent);
293
294         WSACloseEvent((*self)->chatManager.startEvent);
295
296         WSACloseEvent((*self)->chatManager.deleteEvent);
297
298         WSACloseEvent((*self)->chatManager.resetEvents[0]);
299
300         WSACloseEvent((*self)->chatManager.resetEvents[1]);
301
302         WSACloseEvent((*self)->chatManager.resetEvents[2]);
303
304
305
306
307         free((*self));
308
309         (*self) = (NicoLiveStream_P)NULL;
310
311         return;
312 }
313
314
315 ///
316 ///\83n\81[\83g\83r\81[\83g\82Ì\8aÔ\8au\82ð\90Ý\92è\81i\83~\83\8a\95b)
317 ///
318 VOID NicoLiveStream_setHeartBeatMsec(NicoLiveStream_P self,DWORD msec){
319
320         
321         self->chatManager.heartBeatTime  = msec;
322         WSASetEvent(self->chatManager.setHeartBeatTimeEvent);
323         return;
324 }
325
326 ///
327 ///\83n\81[\83g\83r\81[\83g\82Ì\8aÔ\8au\82ð\8eæ\93¾(\83~\83\8a\95b)
328 ///
329 DWORD NicoLiveStream_getHeartBeatMsec(NicoLiveStream_P self){
330
331         return self->chatManager.heartBeatTime;
332
333
334 }
335
336 ///
337 ///\83n\81[\83g\83r\81[\83g\97L\8cø\81E\96³\8cø\90Ý\92è
338 ///
339 VOID NicoLiveStream_setHeartBeatFlag(NicoLiveStream_P self,BOOL flag){
340
341         self->chatManager.heartBeatFlag = flag;
342
343 }
344
345
346 ///
347 ///\83n\81[\83g\83r\81[\83g\97L\8cø\83t\83\89\83O\8eæ\93¾
348 ///
349 BOOL NicoLiveStream_getHeartBeatFlag(NicoLiveStream_P self){
350
351         return self->chatManager.heartBeatFlag;
352
353
354 }
355
356
357 ///
358 ///\83L\81[\83v\83A\83\89\83C\83u\82Ì\8aÔ\8au\82ð\90Ý\92è(\83~\83\8a\95b)
359 ///
360 VOID NicoLiveStream_setKeapALiveMsec(NicoLiveStream_P self,DWORD msec){
361
362         
363         self->chatManager.keepAliveTime = msec;
364         WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
365         return;
366
367 }
368
369 ///
370 ///\83L\81[\83v\83A\83\89\83C\83u\82Ì\8aÔ\8au\82ð\8eæ\93¾(\83~\83\8a\95b)
371 ///
372 DWORD NicoLiveStream_getKeapALiveMsec(NicoLiveStream_P self){
373
374         return self->chatManager.keepAliveTime;
375
376 }
377
378
379 ///
380 ///\83L\81[\83v\83A\83\89\83C\83u\97L\8cø\81E\96³\8cø\90Ý\92è
381 ///
382 VOID NicoLiveStream_setKeapALiveFlag(NicoLiveStream_P self,BOOL flag){
383
384         self->chatManager.keapALiveFlag = flag;
385 }
386
387
388 ///
389 ///\83L\81[\83v\83A\83\89\83C\83u\83t\83\89\83O\8eæ\93¾
390 ///
391 BOOL NicoLiveStream_getKeapALiveFlag(NicoLiveStream_P self){
392
393         return self->chatManager.keapALiveFlag;
394
395 }
396
397 VOID NicoLiveStrream_setResFrom(NicoLiveStream_P self,INT_PTR res){
398
399
400
401         self->res_from = (res < 0 || res > 1000) ? 0 : ((-1) * res);
402
403 }
404
405 INT_PTR NicoLiveStream_getResFrom(NicoLiveStream_P self){
406
407         return (-1) * self->res_from;
408 }
409
410 NLIB_RESULT NicoLiveStream_connect(NicoLiveStream_P self,NicoVideoAuth_P nicoVideoAuth,LPCTSTR url,NicoRecvCallBack callback,LPVOID option){
411
412 #define NICOLIVE_CONNECTIONSTREAM_COOKIE_COUNT          1
413 #define LIVENO_LENGTH                                                           LENGTH_NICOLIVEID
414
415         NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
416
417
418
419
420
421
422
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};
428         
429
430         if(self == NULL)goto end;
431
432         //\91O\82É\82Â\82È\82¢\82Å\82¢\82½\95ú\91\97\82ð\90Ø\92f
433         NicoLiveStream_disConnect(self);
434
435         if(psrech != NULL){
436
437                 psrech += 7;
438
439                 for(;psrech != NULL;psrech = wcsstr(psrech +1,L"/")){
440
441                         pInputLiveNo = psrech + 1;
442
443
444                 }
445         }
446
447         pInputLiveNoEnd = wcsstr(pInputLiveNo,L"?");
448
449         if(pInputLiveNoEnd == NULL){
450
451                 pInputLiveNoEnd = pInputLiveNo + wcslen(pInputLiveNo);
452
453         }
454
455         if(pInputLiveNo == NULL){
456
457                 rslt = NLIB_LIVENO_IS_NULL;
458                 goto end;
459
460         }else if(pInputLiveNoEnd - pInputLiveNo + 2 >= LIVENO_LENGTH - 1){
461
462                 rslt = NLIB_LIVENO_FAILED_TOOBIG;
463                 goto end;
464
465         } else if((wcsncmp(pInputLiveNo,TEXT("lv"),2) == 0)||(( wcsncmp(pInputLiveNo,TEXT("co"),2) == 0) || (wcsncmp(pInputLiveNo,TEXT("ch"),2) == 0) )){
466
467
468                 wcsncpy(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
469
470
471         } else if(_wtoi(pInputLiveNo) != 0){
472
473                 wcscpy(liveNo,L"lv");
474                 wcsncat(liveNo,pInputLiveNo,pInputLiveNoEnd - pInputLiveNo);
475
476         } else {
477
478                 rslt = NLIB_LIVENO_FAILED_UNDEFEINE;
479                 goto end;
480
481
482         }
483
484
485
486
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';
490
491
492
493
494         {
495                 TCHAR objectName[LENGTH_256] = {L"api/getplayerstatus?v="};
496                 wcsncat(objectName,liveNo,sizeof(objectName) / sizeof(objectName[0]));
497
498
499
500         
501
502                 self->sessionManager.getPlayerStatusSession = WinHttpOpenRequest(hWatchLiveNicoConnect,L"GET",objectName,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
503         }
504
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);
509
510         if(rslt != NLIB_ERR_OK){
511
512                 goto end;
513         }
514
515
516
517         //\90\95ú\91\97\83I\83u\83W\83F\83N\83g\82É\8ae\88ø\90\94\82ð\90Ý\92è
518
519         self->callBack = callback;
520         self->option = option;
521
522
523         WSASetEvent(self->chatManager.startEvent);
524
525         self->isConnecting = TRUE;
526
527
528         rslt = NLIB_ERR_OK;
529         //nicoLiveHistory\82ð\8eæ\93¾(\95K\97v\82È\82µ\81H)
530         //GetNicoLiveHistory(self,hWatchLiveNicVideo);
531
532 end:
533
534
535         return rslt;
536 }
537
538
539 NLIB_RESULT NicoLiveStream_sendHeartBeat(NicoLiveStream_P self){
540
541         
542         NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
543
544         if(self->isConnecting == FALSE){
545                 rslt = NLIB_ERR_NOT_LIVECONNECT;
546                 goto end;
547         }
548         if(self == NULL || self->playerStatus.error != NLIB_ERR_OK){
549
550                 rslt = NLIB_ERR_PLAYERSTATUS_ERROR;
551                 goto end;
552
553         }
554
555
556         EnterCriticalSection(&self->sessionManager.cs);
557         {
558                 //HINTERNET hWatchLiveNicoSession = NULL;
559                 //HINTERNET hGetPlayerStatusRequest = NULL;
560                 const UINT_PTR buflen = LENGTH_65536;
561                 LPVOID buffer = self->sessionManager.buffer;
562          
563                 LPTSTR objectName = (LPTSTR)buffer;
564                 LPTSTR indexPtr;
565                 //LPTSTR sendBuffer = (LPTSTR)&objectName[LENGTH_4096];
566                 LPSTR recvBuffer = (LPSTR)&objectName[LENGTH_4096];
567                 DWORD readSize;
568                 DWORD statusCode;
569                 DWORD statusCodeSize = sizeof(statusCode);
570
571                 //hWatchLiveNicoSession = hWatchLiveNicoConnect;
572
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);
579
580
581
582         
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);
585                 
586                 }
587                 if(WinHttpSendRequest(self->sessionManager.heartBeatSession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
588
589                         rslt = NLIB_ERR_FAILED_NETWORK;
590                         goto connectend;
591
592                 }
593
594                 if(WinHttpReceiveResponse(self->sessionManager.heartBeatSession,NULL) == FALSE){
595
596                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
597                         goto connectend;
598
599                 }
600
601
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;
604                         goto connectend;
605                 }
606
607
608                 if (HTTP_STATUS_OK != statusCode){
609                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
610                         goto connectend;
611                 }
612
613
614                 //recvBuffer = (LPSTR)sendBuffer;
615
616
617                 if(ReadHttpBody(self->sessionManager.heartBeatSession,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
618
619                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
620                         goto connectend;
621
622                 }
623
624                 {
625                         
626                         
627                         EnterCriticalSection(&heartBeatCs);
628
629                         XMLParse(&heartBeatContainer,recvBuffer,NicoLiveHeartBeat_ElementStartHandler,NicoLiveHeartBeat_ElementEndHandler,NicoLiveHeartBeat_CharacterDataHandler);
630
631                         self->chatManager.baseVpos = getBaseVpos(heartBeatContainer.heartBeat.time, self->playerStatus.stream.base_time);
632                         setMsec(self->chatManager.commentStartTime);
633
634                         self->callBack(NICOLIVE_EVENT_SEND_HEARTBEAT,self,self->option,(NICOLIVE_PARAM)&heartBeatContainer.heartBeat,(NICOLIVE_PARAM)NULL);
635
636                         ZeroMemory(&heartBeatContainer.heartBeat,sizeof(heartBeatContainer.heartBeat));
637
638                         ZeroMemory(heartBeatContainer.is_restrictBuff,heartBeatContainer.is_restrictSize);
639
640                         ZeroMemory(heartBeatContainer.ticketBuff,heartBeatContainer.ticketSize);
641
642                         heartBeatContainer.heartBeat.is_restrict = heartBeatContainer.is_restrictBuff;
643
644                         heartBeatContainer.heartBeat.ticket = heartBeatContainer.ticketBuff;
645
646                         LeaveCriticalSection(&heartBeatCs);
647
648
649                 }
650
651                 rslt = NLIB_ERR_OK;
652 connectend:
653                 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
654                 LeaveCriticalSection(&self->sessionManager.cs);
655
656
657                 
658
659         }
660 end:
661         
662
663         return rslt;
664 }
665
666 VOID NicoLiveStream_disConnect(NicoLiveStream_P self){
667
668         if(self == NULL)goto end;
669
670         while(WSAResetEvent(self->chatManager.startEvent) == FALSE);
671         while(WSASetEvent(self->chatManager.endEvent)== FALSE);
672
673         
674
675
676
677         WSAWaitForMultipleEvents(sizeof(self->chatManager.resetEvents) / sizeof(self->chatManager.resetEvents[0]),self->chatManager.resetEvents,TRUE,WSA_INFINITE,FALSE);
678
679
680
681         //nicoLiveStream_Initialize(*self);
682         ZeroMemory(&self->playerStatus,sizeof(self->playerStatus));
683         WSAResetEvent(self->chatManager.endEvent);
684         
685         WinHttpCloseHandle(self->sessionManager.getPlayerStatusSession);
686         self->sessionManager.getPlayerStatusSession = NULL;
687         WinHttpCloseHandle(self->sessionManager.heartBeatSession);
688         self->sessionManager.heartBeatSession = NULL;
689
690
691
692         self->isConnecting = FALSE;
693
694 end:
695
696
697         return;
698
699
700
701 }
702
703
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>"
706
707 NLIB_RESULT NicoLiveStream_sendChat(NicoLiveStream_P self,LPCTSTR chatbuf,LPCTSTR *mail,LPCTSTR *extends){
708
709         NLIB_RESULT rslt = NLIB_ERR_CODE_NOTSET;
710         EnterCriticalSection(&self->sessionManager.cs);
711         
712         {
713                 const UINT_PTR buflen = LENGTH_65536 * 4;
714                 LPVOID chunk = self->sessionManager.buffer;
715
716                 LPSTR postKey;
717                 LPSTR postKeyBuf = (LPSTR)chunk;
718                 LPTSTR postKeyReqBuf = (LPTSTR)&postKeyBuf[NICOLIVE_SENDCHATBUFLEN];
719                 LPTSTR cookieBuf = &postKeyReqBuf[NICOLIVE_SENDCHATBUFLEN];
720                 DWORD statusCode;
721                 DWORD statusCodeSize = sizeof(statusCode);
722                 DWORD readSize;
723
724                 //HINTERNET hWatchLiveNicoVideo = NULL;
725                 HINTERNET hGetPostKeySession = NULL;
726                 
727
728                 if(self->isConnecting == FALSE){
729                         rslt = NLIB_ERR_NOT_LIVECONNECT;
730                         goto errorend;
731                 }
732                 if(chatbuf == NULL || wcslen(chatbuf) >= LENGTH_1024){
733
734                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
735                         goto errorend;
736
737                 }
738
739
740                 //postkey\8eæ\93¾
741                 _swprintf(postKeyReqBuf,L"api/getpostkey?thread=%u&block_no=%u",self->playerStatus.ms.thread,self->chatManager.chatNo / 100);
742
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);
745
746
747                 //_swprintf(cookieBuf,L"Cookie: %s; %s",self->userSession,self->nicoLiveHistory);
748                 _swprintf(cookieBuf,L"Cookie: %s",self->userSession);
749
750                 if(WinHttpSendRequest(hGetPostKeySession,self->userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
751
752                         rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
753                         goto errorend;
754
755                 }
756
757
758                 if(WinHttpReceiveResponse(hGetPostKeySession,NULL) == FALSE){
759
760                         rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
761                         goto errorend;
762
763                 }
764
765
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;
768                         goto errorend;
769                 }
770
771
772                 if (HTTP_STATUS_OK != statusCode){
773                         rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
774                         goto errorend;
775                 }
776
777
778
779
780
781                 if(ReadHttpBody(hGetPostKeySession,(LPBYTE)postKeyBuf,buflen,&readSize) == FALSE){
782
783                         rslt = NLIB_ERR_LIVE_GETPOSTKEY_FAILED;
784                         goto errorend;
785
786                 }
787                 postKeyBuf[readSize] = '\0';
788                 postKey = strstr(postKeyBuf,"=") + 1;
789
790
791                 {
792                         LPSTR buffer = (LPSTR)&cookieBuf[NICOLIVE_SENDCHATBUFLEN];
793                         LPSTR indexPtr;
794                         LPSTR mailBuf;
795                         LPSTR extendBuf;
796                 
797                         //mail\83R\83}\83\93\83h\8dì\90¬
798                         if(mail == NULL || mail[0] == NULL){
799
800                                 mailBuf = "";
801
802                         } else {
803                                 INT_PTR len;
804                                 mailBuf = (LPSTR)postKeyReqBuf;
805                                 indexPtr = mailBuf;
806                                 strcpy(indexPtr,"mail=\"");
807                                 indexPtr += strlen(indexPtr);
808
809                                 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
810                                 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
811                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
812                                         goto errorend;
813
814                                 }
815
816                                 
817                                         WideToMB(CP_UTF8,mail[0],indexPtr,len);
818                                         indexPtr += strlen(indexPtr);
819
820
821                                         for(mail++;mail[0] != NULL;mail++){
822
823                                                 indexPtr[0] = ' ';
824                                                 indexPtr++;
825
826                                                 len =  NICOLIVE_SENDCHATBUFLEN - (indexPtr - mailBuf) - 1;
827
828                                                 if(GetLenToMB(CP_UTF8,mail[0]) >= len){
829                                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
830                                                         goto errorend;
831
832                                                 }
833
834                                                 WideToMB(CP_UTF8,mail[0],indexPtr,len);
835                                                 indexPtr += strlen(indexPtr);
836
837                                         }
838                                 
839                                 strcpy(indexPtr,"\"");
840
841
842
843
844                         }
845
846                         //\8ag\92£\91®\90«\8dì\90¬
847                         if(extends == NULL || extends[0] == NULL){
848
849                                 extendBuf = "";
850
851                         } else {
852                                 INT_PTR len;
853                                 extendBuf  =(LPSTR)cookieBuf;
854                                 indexPtr = extendBuf;
855
856
857                                 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
858
859                                 if(GetLenToMB(CP_UTF8,extends[0]) >= len){
860                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
861                                         goto errorend;
862
863                                 }
864                                 WideToMB(CP_UTF8,extends[0],indexPtr,len);
865
866                                 indexPtr += strlen(indexPtr);
867
868                                 strcpy(indexPtr,"=\"");
869                                 indexPtr += strlen(indexPtr);
870
871
872                                 len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
873
874                                 if(GetLenToMB(CP_UTF8,extends[1]) >= len){
875                                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
876                                         goto errorend;
877
878                                 }
879                                 WideToMB(CP_UTF8,extends[1],indexPtr,len);
880
881
882                                 for(extends+= 2;extends[0] != NULL;extends+=2){
883
884                                         indexPtr[0] = ' ';
885                                         indexPtr++;
886
887                                         len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
888
889                                         if(GetLenToMB(CP_UTF8,extends[0]) >= len){
890                                                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
891                                                 goto errorend;
892
893                                         }
894                                         WideToMB(CP_UTF8,extends[0],indexPtr,len);
895
896                                         indexPtr += strlen(indexPtr);
897
898                                         indexPtr[0] = '=';
899                                         indexPtr++;
900
901
902                                         len = NICOLIVE_SENDCHATBUFLEN - (indexPtr - extendBuf) - 1;
903
904                                         if(GetLenToMB(CP_UTF8,extends[1]) >= len){
905                                                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
906                                                 goto errorend;
907
908                                         }
909                                         WideToMB(CP_UTF8,extends[1],indexPtr,len);
910
911
912
913                                 }
914                                 indexPtr += strlen(indexPtr);
915                                 strcpy(indexPtr,"\"");
916
917
918
919                         }
920
921                         //\83`\83\83\83b\83g\91\97\90M\83R\83\81\83\93\83g\8dì\90¬
922                         {
923                                 indexPtr = buffer;
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);
951                         
952                         
953                                 timeBeginPeriod(1);
954                                 sprintf(indexPtr,"%u",(self->chatManager.baseVpos + ((timeGetTime() - self->chatManager.commentStartTime) / 10)));
955                                 timeEndPeriod(1);
956                         
957                                 indexPtr += strlen(indexPtr);
958                                 strcpy(indexPtr,"\"");
959                                 indexPtr += strlen(indexPtr);
960
961                                 if(strlen(mailBuf) > 0 && strlen(extendBuf) > 0){
962
963                                         indexPtr[0] = ' ';
964                                         indexPtr++;
965                                         strcpy(indexPtr,mailBuf);
966                                         indexPtr += strlen(indexPtr);
967
968                                         indexPtr[0] = ' ';
969                                         indexPtr++;
970
971                                         strcpy(indexPtr,extendBuf);
972                                         indexPtr += strlen(indexPtr);
973
974
975                                 } else if(strlen(mailBuf) > 0){
976                                         indexPtr[0] = ' ';
977                                         indexPtr++;
978                                         strcpy(indexPtr,mailBuf);
979                                         indexPtr += strlen(indexPtr);
980
981                                 } else if(strlen(extendBuf) > 0){
982                                         indexPtr[0] = ' ';
983                                         indexPtr++;
984                                         strcpy(indexPtr,extendBuf);
985                                         indexPtr += strlen(indexPtr);
986                                 }
987                                 strcpy(indexPtr,">");
988                                 indexPtr += strlen(indexPtr);
989                                 {
990                                         LPTSTR sendBuf = (LPTSTR)&buffer[NICOLIVE_SENDCHATBUFLEN * 4];
991                                         LPTSTR sendPtr = sendBuf;
992                                         LPCTSTR endPtr= chatbuf + wcslen(chatbuf);
993
994
995                                         //convertTEXT(indexPtr,chatbuf,indexPtr,endPtr);
996
997                                         for(;(chatbuf) <= (endPtr);(chatbuf)++){
998                                                 switch(chatbuf[0]){
999                                                 case L'&':
1000                                                         wcscpy((sendBuf),L"&amp;");
1001                                                         (sendBuf) += wcslen(sendBuf);
1002                                                         break;
1003                                                 case L'<':
1004                                                         wcscpy((sendBuf),L"&lt;");
1005                                                         (sendBuf) += wcslen(sendBuf);
1006                                                         break;
1007                                                 case L'>':
1008                                                         wcscpy((sendBuf),L"&gt;");
1009                                                         (sendBuf) += wcslen(sendBuf);
1010                                                         break;
1011                                                 case L'\"':
1012                                                         wcscpy((sendBuf),L"&quot;");
1013                                                         (sendBuf) += wcslen(sendBuf);
1014                                                         break;
1015                                                 case L'\'':
1016                                                         wcscpy((sendBuf),L"&apos;");
1017                                                         (sendBuf) += wcslen(sendBuf);
1018                                                         break;
1019                                                 default:
1020                                                         sendBuf[0] = chatbuf[0];
1021                                                         (sendBuf)++;
1022                                                         break;
1023                                                 }
1024                                         }
1025
1026
1027                                         WideToMB(CP_UTF8,sendPtr,indexPtr,NICOLIVE_SENDCHATBUFLEN * 4 - (indexPtr - buffer) - 1);
1028                                         indexPtr += strlen(indexPtr);
1029                                 
1030                                 }
1031                                 strcpy(indexPtr,"</chat>");
1032                                 indexPtr[strlen(indexPtr)] = '\0';
1033
1034
1035
1036                                 {
1037                                         INT_PTR sendLen = 0;
1038                                         INT_PTR sentLen = 0;
1039                                         INT_PTR max = strlen(buffer) + 1;
1040
1041                                         do{
1042                                                 sendLen = send(self->chatManager.sock,buffer,max - sentLen,0);
1043                                                 sentLen += sendLen;
1044                                         } while(sendLen > 0);
1045
1046                                 }
1047                         }
1048                 }
1049
1050                 rslt = NLIB_ERR_OK;
1051                 
1052 errorend:
1053         
1054                 WinHttpCloseHandle(hGetPostKeySession);
1055
1056                 ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1057                 LeaveCriticalSection(&self->sessionManager.cs);
1058                 }
1059
1060
1061
1062         return rslt;
1063
1064 }
1065
1066
1067
1068
1069
1070
1071
1072 //
1073 //\83C\83\93\83\89\83C\83\93\8aÖ\90\94
1074 //
1075
1076
1077
1078 NLIB_RESULT GetPlayerStatus(NicoLivePlayerStatus_P self,LPCTSTR userSession,HINTERNET hConnect,LPVOID buffer){
1079
1080         NLIB_RESULT rslt = NLIB_ERR_OK;
1081
1082         
1083         {
1084                 //HINTERNET hWatchLiveNicoSession = NULL;
1085                 //HINTERNET hGetPlayerStatusRequest = NULL;
1086                 const UINT_PTR buflen = LENGTH_65536;
1087                 //LPVOID buffer = ;
1088                 //LPTSTR sendBuffer;
1089                 LPSTR recvBuffer = (LPSTR)buffer;
1090                 DWORD readSize;
1091                 DWORD statusCode;
1092                 DWORD statusCodeSize = sizeof(statusCode);
1093
1094
1095         
1096
1097                 if(WinHttpSendRequest(hConnect,userSession,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1098
1099                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1100                         goto end;
1101
1102                 }
1103
1104                 if(WinHttpReceiveResponse(hConnect,NULL) == FALSE){
1105
1106                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1107                         goto end;
1108
1109                 }
1110
1111
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;
1114                         goto end;
1115                 }
1116
1117
1118                 if (HTTP_STATUS_OK != statusCode){
1119                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1120                         goto end;
1121                 }
1122
1123
1124                 //recvBuffer = (LPSTR)sendBuffer;
1125
1126
1127                 if(ReadHttpBody(hConnect,(LPBYTE)recvBuffer,buflen,&readSize) == FALSE){
1128
1129                         rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1130                         goto end;
1131
1132                 }
1133
1134                 recvBuffer[readSize] = '\0';
1135
1136                 recvBuffer = strstr(recvBuffer,"<");
1137
1138                 dumpln_mb(CP_UTF8,"%s",recvBuffer);
1139
1140
1141                 XMLParse(self,recvBuffer,NPlayerStatus_ElementStartHandler,NPlayerStatus_ElementEndHandler,NPlayerStatus_CharacterDataHandler);
1142                 rslt = self->error;
1143                 if(rslt != NLIB_ERR_OK){
1144
1145                         goto end;
1146                 }
1147         }
1148
1149 end:
1150
1151         
1152
1153         
1154
1155         return rslt;
1156
1157 }
1158
1159
1160 #define GETNICOLIVEHIS_OBJNAMELENGTH    LENGTH_256
1161 #define GETNICOLIVEHIS_COOKIELENGTH             LENGTH_512
1162
1163 static INLINE NLIB_RESULT GetNicoLiveHistory(NicoLiveStream_P self,HINTERNET hConnect){
1164
1165         NLIB_RESULT rslt = NLIB_ERR_OK;
1166
1167         EnterCriticalSection(&self->sessionManager.cs);
1168         {
1169         //HINTERNET hNicoVideoConnect = NULL;
1170         HINTERNET hStreamBrowse = NULL;
1171
1172
1173         TCHAR objectName[GETNICOLIVEHIS_OBJNAMELENGTH] = {L"/watch/"};
1174         TCHAR cookie[GETNICOLIVEHIS_COOKIELENGTH] = {L"Cookie: "};
1175         DWORD statusCode;
1176         DWORD statusCodeSize = sizeof(statusCode);
1177         DWORD chunkSize = LENGTH_65536;
1178         LPVOID chunkMemory =self->sessionManager.buffer;
1179         
1180
1181
1182         LPTSTR buffer = (LPTSTR)chunkSize;
1183
1184
1185
1186         if((GETNICOLIVEHIS_OBJNAMELENGTH - wcslen(objectName) <= wcslen(self->playerStatus.stream.id)) || GETNICOLIVEHIS_COOKIELENGTH - wcslen(cookie) <= wcslen(self->userSession)){
1187
1188                 rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1189                 goto end;
1190         } 
1191
1192         wcscat(objectName,self->playerStatus.stream.id);
1193         wcscat(cookie,self->userSession);
1194
1195         
1196
1197         //hNicoVideoConnect = hConnect;
1198
1199         
1200
1201         hStreamBrowse = WinHttpOpenRequest(hNicoVideoConnect,L"GET",objectName,L"1.1",(LPCTSTR)WINHTTP_NO_REFERER,(LPCTSTR*)WINHTTP_DEFAULT_ACCEPT_TYPES,0);
1202
1203
1204
1205
1206         if(WinHttpSendRequest(hStreamBrowse,cookie,-1,WINHTTP_NO_REQUEST_DATA,0,0,0) == FALSE){
1207
1208                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1209                 goto end;
1210
1211         }
1212
1213         if(WinHttpReceiveResponse(hStreamBrowse,NULL) == FALSE){
1214
1215                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1216                 goto end;
1217
1218         }
1219
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;
1222                 goto end;
1223         }
1224
1225
1226         if (HTTP_STATUS_OK != statusCode){
1227                 rslt = NLIB_GETPLAYERSTATUS_FAILED_CONNECT;
1228                 goto end;
1229         }
1230
1231
1232
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;
1235                 goto end;
1236         }
1237
1238         {
1239                 LPTSTR start =wcsstr(buffer,L"nicolivehistory=");
1240
1241                 LPTSTR end = wcsstr(start,L";");
1242
1243                 UINT_PTR length = end - start;
1244
1245                 if(length >= sizeof(self->nicoLiveHistory)){
1246                         rslt = NLIB_ERR_BUFFER_TOOLITTLE;
1247                         goto end;
1248
1249                 }
1250
1251                 wcsncpy(self->nicoLiveHistory,start,length);
1252                 self->nicoLiveHistory[length] = L'\0';
1253
1254         }
1255 end:
1256
1257         WinHttpCloseHandle(hStreamBrowse);
1258
1259         }
1260         ZeroMemory(self->sessionManager.buffer,sizeof(self->sessionManager.buffer));
1261         LeaveCriticalSection(&self->sessionManager.cs);
1262
1263
1264         return rslt;
1265
1266
1267
1268 }
1269
1270
1271
1272
1273
1274
1275
1276
1277 static unsigned int WINAPI  NicoLiveKeapALiveThread(void* lpBuffer){
1278
1279         unsigned int rslt = 0;
1280
1281         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1282
1283         rslt = loopCommon(self,self->chatManager.setKeepAliveTimeEvent,self->chatManager.resetEvents[2],self->chatManager.onKeepAlliveSend,&self->chatManager.keepAliveTime);
1284
1285         _endthreadex(rslt);
1286
1287         return rslt;
1288 }
1289
1290 static unsigned int WINAPI  NicoLiveHeartBeatThread(void* lpBuffer){
1291
1292         unsigned int rslt = 0;
1293
1294         NicoLiveStream_P self = (NicoLiveStream_P)lpBuffer;
1295
1296
1297         rslt = loopCommon(self,self->chatManager.setHeartBeatTimeEvent,self->chatManager.resetEvents[1],self->chatManager.onHeartBeatSend,&self->chatManager.heartBeatTime);
1298
1299
1300
1301         _endthreadex(rslt);
1302
1303         return rslt;
1304 }
1305 static unsigned int loopCommon(NicoLiveStream_P self,WSAEVENT sendEvent,WSAEVENT resetEvent ,NicoLiveOnSend nicoLiveOnSend,LPDWORD time){
1306
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Ê
1311         DWORD endResult;
1312
1313         while(TRUE){
1314 restart:
1315                 WSASetEvent(resetEvent);
1316                 
1317                 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1318
1319
1320                 //\83G\83\89\81[\82Ì\8fê\8d\87
1321                 if(dwResult == WSA_WAIT_FAILED){
1322
1323                         goto err;
1324                 }
1325
1326
1327                 switch(dwResult - WSA_WAIT_EVENT_0){
1328
1329                 case 0:
1330
1331                         goto end;
1332
1333                 case 1:
1334                         WSAResetEvent(resetEvent);
1335                         break;
1336
1337                 case 2:
1338                         continue;
1339
1340
1341                 default:
1342
1343                         goto err;
1344
1345                 }
1346
1347                 while(TRUE){
1348                         WSAResetEvent(sendEvent);
1349                         endResult = WSAWaitForMultipleEvents(sizeof(streamEvent) / sizeof(streamEvent[0]),streamEvent,FALSE,*time,FALSE);
1350
1351                         if(endResult == WSA_WAIT_TIMEOUT){
1352
1353                                 nicoLiveOnSend(self);
1354                                 //dumpln(TEXT("onSend"));
1355
1356                                 _heapmin();
1357                         } else{ 
1358                                 switch(endResult - WSA_WAIT_EVENT_0){
1359
1360                                 case 0:
1361                                         goto restart;
1362
1363                                 case 1:
1364                                         break;
1365
1366                                 default:
1367                                         goto err;
1368                                 }
1369                         } 
1370                 }
1371
1372
1373
1374
1375         }
1376
1377 end:
1378         return rslt;
1379
1380 err:
1381         _beginthread(NicoLiveError,0,self);
1382         rslt = 1;
1383         goto end;
1384 }
1385
1386 static VOID OnSendHeartBeat(NicoLiveStream_P self){
1387
1388         if(self->chatManager.heartBeatFlag){
1389                 NicoLiveStream_sendHeartBeat(self);
1390         }
1391
1392 }
1393
1394 static VOID OnSendKeepAllive(NicoLiveStream_P self){
1395         
1396         if(self->chatManager.keapALiveFlag){
1397                 LPCTSTR mail[2] = {L"184",NULL};
1398                 NicoLiveStream_sendChat(self,L"/keapalive",mail,NULL);
1399         }
1400
1401 }
1402
1403 #define NICOLIVE_RECEVE_CHAT_LENGTH     LENGTH_2048
1404 #define NICOLIVE_REQUEST_CHAT_LENGTH    LENGTH_256
1405 static unsigned int WINAPI NicoLiveRecvChat(void* lpBuffer){
1406
1407
1408         unsigned int rslt = 0;
1409
1410         //LPTSTR user_id = NULL;
1411         //LPTSTR name = NULL;
1412         //LPTSTR chatBuf = NULL;
1413
1414
1415
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Ê
1423
1424         
1425
1426         while(TRUE){
1427
1428                 WSASetEvent(self->chatManager.resetEvents[0]);
1429
1430                 dwResult = WSAWaitForMultipleEvents(sizeof(events) / sizeof(events[0]),events,FALSE,WSA_INFINITE,FALSE);
1431
1432
1433                 //\83G\83\89\81[\82Ì\8fê\8d\87
1434                 if(dwResult == WSA_WAIT_FAILED){
1435
1436                         goto err;
1437                 }
1438
1439
1440                 switch(dwResult - WSA_WAIT_EVENT_0){
1441
1442                 case 0:
1443
1444                         goto end;
1445
1446                 case 1:
1447                         WSAResetEvent(self->chatManager.resetEvents[0]);
1448                         break;
1449
1450                 case 2:
1451                         continue;
1452
1453                 default:
1454
1455                         goto err;
1456
1457                 }
1458
1459
1460                 sendLen = 0;
1461                 sentLen = 0;
1462
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);
1465
1466
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;
1470                         goto err;
1471                 }
1472
1473
1474
1475
1476
1477
1478                 if(NICOLIVE_REQUEST_CHAT_LENGTH <= _scprintf(sendFormat,self->playerStatus.ms.thread,self->res_from)){
1479
1480                         self->error = NLIB_ERR_BUFFER_TOOLITTLE;
1481                         rslt = -1;
1482                         goto err;
1483
1484
1485                 }
1486
1487                 sprintf(requestChat,sendFormat,self->playerStatus.ms.thread,self->res_from);
1488
1489
1490                 //
1491                 //\83R\83\81\83\93\83g\8eó\90M\97v\8b\81\91\97\90M\8f\88\97\9d
1492                 //
1493                 {
1494                         int len;
1495                         sendLen = strlen(requestChat) + 1;
1496                         do{
1497                                 len = send(self->chatManager.sock,requestChat,sendLen,0);
1498                                 if(len == SOCKET_ERROR){
1499                                         self->error = NLIB_ERR_FAILED_NETWORK;
1500                                         rslt = -1;
1501
1502                                         goto err;
1503
1504                                 }
1505
1506                                 sentLen = len;
1507                         }while(sentLen < sendLen);
1508                 }
1509
1510
1511                 if(NicoLiveRecvChatLoop(self) == FALSE){
1512                         goto err;
1513                 }
1514
1515                 
1516         }
1517
1518
1519
1520
1521 err:
1522
1523         _beginthread(NicoLiveError,0,self);
1524
1525 end:
1526
1527
1528
1529         closesocket(self->chatManager.sock);
1530         _endthreadex(rslt);
1531
1532         return rslt;
1533
1534
1535
1536
1537
1538 }
1539
1540
1541
1542
1543
1544 static BOOL NicoLiveRecvChatLoop(NicoLiveStream_P self){
1545
1546
1547         //
1548         //\83R\83\81\83\93\83g\8eó\90M\8f\88\97\9d
1549         //
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·
1555
1556
1557
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
1561
1562         
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·
1565
1566
1567         WSAEVENT hRecvEvent = NULL;
1568
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;
1576
1577         commentBuf = (LPTSTR)malloc(commentBufSize);
1578         mailCountBuf = (LPTSTR*)malloc(mailCountBufSize);
1579
1580         //\90Ø\92f\82³\82ê\82é\82Ü\82Å\83\8b\81[\83v
1581         while(1){
1582
1583
1584
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);
1587
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);
1590
1591                 //\83G\83\89\81[\82Ì\8fê\8d\87
1592                 if(dwResult == WSA_WAIT_FAILED){
1593
1594                         goto err;
1595                 }
1596
1597
1598
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){
1601
1602                         WSAEnumNetworkEvents(self->chatManager.sock,hRecvEvent,&netEvents);
1603
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){
1606
1607
1608                                 recevedLen = recv(self->chatManager.sock,&self->chatManager.recvBuf[messageBufLen],(sizeof(self->chatManager.recvBuf) - 1) - messageBufLen ,0);
1609
1610                                 if(recevedLen == SOCKET_ERROR){
1611                                         self->error = NLIB_ERR_FAILED_NETWORK;
1612
1613                                         goto err;
1614                                 }
1615
1616                                 self->chatManager.recvBuf[messageBufLen + recevedLen] = '\0';
1617
1618
1619
1620
1621
1622
1623                                 NicoLiveParseComment(self,commentBuf,messageBufLen + recevedLen,mailCountBuf,&mailCountBufSize,&commentBufSize);
1624
1625
1626
1627
1628
1629                         } else if(netEvents.lNetworkEvents && FD_CLOSE){
1630
1631                                 goto end;
1632
1633                         }//if(netEvents.lNetworkEvents & FD_READ)
1634
1635                 } else if(dwResult - WSA_WAIT_EVENT_0 == 1){
1636
1637                         goto end;
1638
1639                 }//if(dwResult - WSA_WAIT_EVENT_0 == 0)
1640         }
1641
1642
1643 err:
1644
1645         rslt = FALSE;
1646
1647 end:
1648
1649         free(commentBuf);
1650         free(mailCountBuf);
1651         WSACloseEvent(hRecvEvent);
1652
1653         return rslt;
1654 }
1655
1656
1657
1658
1659 static VOID  NicoLiveParseComment(NicoLiveStream_P self,LPTSTR commentBuf,UINT_PTR endSize,LPTSTR* mailCountBuf,SIZE_T* mailCountBufSize,SIZE_T* commentBufSize){
1660
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^
1681
1682
1683
1684         recvBufTmp = &self->chatManager.recvBuf[0];
1685         recvEndPoint = &self->chatManager.recvBuf[endSize];
1686
1687
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;
1701
1702
1703
1704         nicoLiveThreadCommentBase.last_res = L"";
1705         nicoLiveThreadCommentBase.thread = L"";
1706         nicoLiveThreadCommentBase.ticket = L"";
1707
1708
1709         nicoLiveSendResultCommentBase.no = L"";
1710         nicoLiveSendResultCommentBase.status = L"";
1711         nicoLiveSendResultCommentBase.thread = L"";
1712
1713         
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){
1716
1717
1718                 commentSizeCh = sizeof(TCHAR) * GetLenToWide(CP_UTF8,recvBufTmp);
1719                 extendMalloc(commentBuf,LPTSTR,*commentBufSize,commentSizeCh);
1720                 MBToWide(CP_UTF8,recvBufTmp,commentBuf,*commentBufSize);
1721
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){
1725
1726                         indexPtr += wcslen(L"<thread ");
1727                         skipXMLSPACE(indexPtr);
1728
1729
1730
1731
1732                         nicoLiveThreadComment = nicoLiveThreadCommentBase;
1733
1734                         while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1735                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1736
1737
1738                                 nameLen = attrNameEnd - attrNameStart;
1739                                 if(wcsncmp(attrNameStart,L"ticket",nameLen) == 0){
1740
1741
1742                                         partString(nicoLiveThreadComment.ticket,attrValueStart,attrValueEnd);
1743                                         wcscpy(self->ticket,nicoLiveThreadComment.ticket);
1744
1745                                 } else if(wcsncmp(attrNameStart,L"last_res",nameLen) == 0){
1746
1747                                         partString(nicoLiveThreadComment.last_res,attrValueStart,attrValueEnd);
1748
1749
1750                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1751
1752                                         partString(nicoLiveThreadComment.thread,attrValueStart,attrValueEnd);
1753                                 } else if(wcsncmp(attrNameStart,L"server_time",nameLen) == 0){
1754
1755                                         NicoLiveStream_setVpos((*self),attrValueStart);
1756
1757                                         partString(nicoLiveThreadComment.server_time,attrValueStart,attrValueEnd);
1758                                 }
1759
1760                                 skipXMLSPACE(indexPtr);
1761                         }
1762
1763                         
1764
1765                         self->callBack(NICOLIVE_EVENT_RECEVE_CONNECTRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveThreadComment,self->chatManager.chatNo);
1766
1767                         //chat\83m\81[\83h\82Ì\8fê\8d\87
1768                 } else if((indexPtr = wcsstr(commentBuf,L"<chat ")) != NULL){
1769
1770                         indexPtr += wcslen(L"<chat ");
1771                         skipXMLSPACE(indexPtr);
1772
1773
1774
1775                         
1776                         nicoLiveChat = nicoLiveChatBase;
1777
1778                         while(wcsncmp(indexPtr,L">",wcslen(L">"))){
1779
1780                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1781
1782                                 nameLen = attrNameEnd - attrNameStart;
1783
1784
1785                                 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1786
1787                                         partString(nicoLiveChat.no,attrValueStart,attrValueEnd);
1788
1789                                 } else if(wcsncmp(attrNameStart,L"date",nameLen) == 0){
1790
1791                                         NicoLiveStream_setVpos((*self),attrValueStart);
1792
1793                                         partString(nicoLiveChat.date,attrValueStart,attrValueEnd);
1794
1795                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1796
1797                                         partString(nicoLiveChat.thread,attrValueStart,attrValueEnd);
1798
1799                                 } else if(wcsncmp(attrNameStart,L"premium",nameLen) == 0){
1800
1801                                         partString(nicoLiveChat.premium,attrValueStart,attrValueEnd);
1802
1803                                 }  else if(wcsncmp(attrNameStart,L"anonymity",nameLen) == 0){
1804
1805                                         partString(nicoLiveChat.anonymity,attrValueStart,attrValueEnd);
1806
1807
1808                                 } else if(wcsncmp(attrNameStart,L"locale",nameLen) == 0){
1809
1810                                         partString(nicoLiveChat.locale,attrValueStart,attrValueEnd);
1811
1812                                 } else if(wcsncmp(attrNameStart,L"vpos",nameLen) == 0){
1813
1814                                         partString(nicoLiveChat.vpos,attrValueStart,attrValueEnd);
1815
1816                                 } else if(wcsncmp(attrNameStart,L"user_id",nameLen) == 0){
1817
1818                                         partString(nicoLiveChat.user_id,attrValueStart,attrValueEnd);
1819
1820                                 } else if(wcsncmp(attrNameStart,L"name",nameLen) == 0){
1821
1822                                         partString(nicoLiveChat.name,attrNameStart,attrValueEnd);
1823
1824                                 } else if(wcsncmp(attrNameStart,L"mail",nameLen) == 0){
1825
1826                                         nicoLiveChat.mailCount = 1;
1827
1828
1829                                         for(mailIndexPtr = attrValueStart;mailIndexPtr <= attrValueEnd;mailIndexPtr++){
1830
1831                                                 if(mailIndexPtr[0] == L' '){
1832
1833                                                         nicoLiveChat.mailCount++;
1834
1835                                                 }
1836
1837                                         }
1838
1839                                         extendMalloc(mailCountBuf,LPTSTR*,*mailCountBufSize,nicoLiveChat.mailCount);
1840
1841                                         nicoLiveChat.mail = mailCountBuf;
1842                                         mailCountBuf[0] = NULL;
1843
1844                                         for(mailIndex = mailCountBuf,mailIndexPtr = attrValueStart,mailIndex[0] = mailIndexPtr;mailIndexPtr < attrValueEnd;mailIndexPtr++){
1845
1846
1847                                                 if(mailIndexPtr[0] == L' '){
1848                                                         mailIndex++;
1849                                                         mailIndex[0] = mailIndexPtr + 1;
1850                                                         mailIndexPtr[0] = L'\0';
1851
1852
1853                                                 }
1854
1855                                         }
1856
1857                                         mailIndexPtr[0] = L'\0';
1858
1859                                 }
1860
1861                                 skipXMLSPACE(indexPtr);
1862                         }
1863
1864                         indexPtr++;
1865                         xmlTextPtr = indexPtr;
1866                         xmlTextEnd = wcsstr(indexPtr,L"<");
1867                         convertXMLTEXT(nicoLiveChat.chatBuf,indexPtr,xmlTextPtr,xmlTextEnd);
1868
1869
1870
1871                         self->chatManager.chatNo =  wcstoul(nicoLiveChat.no,NULL,10);
1872
1873
1874                         
1875                         self->chatManager.commentCountSum++;
1876                         isReceveChat = TRUE;
1877
1878                         check((_heapchk() == _HEAPOK),TEXT("\83q\81[\83v\83G\83\89\81[\82Å\82·"));
1879
1880                         if((wcscmp(nicoLiveChat.chatBuf,L"/disconnect") == 0 && wcscmp(nicoLiveChat.premium,L"2") == 0)){
1881
1882                                 
1883                                 _beginthread(NicoLiveSelfDisconnect,0,self);
1884                         }
1885                         self->callBack(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&nicoLiveChat,self->chatManager.commentCountSum);
1886                         
1887
1888                         //chat_result\83m\81[\83h\82Ì\8fê\8d\87
1889                 } else if((indexPtr = wcsstr(commentBuf,L"<chat_result ")) != NULL){
1890
1891                         indexPtr += wcslen(L"<chat_result ");
1892
1893                         nicoLiveSendResultComment = nicoLiveSendResultCommentBase;
1894
1895                         while(wcsncmp(indexPtr,L"/>",wcslen(L"/>")) != 0){
1896                                 parseAttr(indexPtr,attrNameStart,attrNameEnd,attrValueStart,attrValueEnd);
1897
1898
1899                                 nameLen = attrNameEnd - attrNameStart;
1900                                 if(wcsncmp(attrNameStart,L"no",nameLen) == 0){
1901
1902
1903                                         partString(nicoLiveSendResultComment.no,attrValueStart,attrValueEnd);
1904
1905                                 } else if(wcsncmp(attrNameStart,L"status",nameLen) == 0){
1906
1907                                         partString(nicoLiveSendResultComment.status,attrValueStart,attrValueEnd);
1908
1909
1910                                 } else if(wcsncmp(attrNameStart,L"thread",nameLen) == 0){
1911
1912                                         partString(nicoLiveSendResultComment.thread,attrValueStart,attrValueEnd);
1913                                 }
1914
1915                                 skipXMLSPACE(indexPtr);
1916                         }
1917
1918                         //\83L\81[\83v\83A\83\89\83C\83u\83\8a\83Z\83b\83g
1919                         WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
1920
1921                         self->callBack(NICOLIVE_EVENT_RECEVE_CHATSENDRESULT,self,self->option,(NICOLIVE_PARAM)&nicoLiveSendResultComment,(NICOLIVE_PARAM)NULL);
1922
1923                 }
1924
1925         }
1926
1927         if(recvBufTmp == recvEndPoint && isReceveChat){
1928                 self->callBack(NICOLIVE_EVENT_RECEVE_CHATSETTLE,self,self->option,self->chatManager.chatNo,self->chatManager.commentCountSum);
1929         }
1930
1931
1932
1933
1934         strcpy(&self->chatManager.recvBuf[0],recvBufTmp);
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945         return;
1946
1947 }
1948
1949
1950
1951 static void NicoLiveError(void *buf){
1952
1953         NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1954
1955         nl->callBack(NICOLIVE_EVENT_ERR_CONNECT,nl,nl->option,(NICOLIVE_PARAM)NULL,(NICOLIVE_PARAM)NULL);
1956
1957         NicoLiveStream_disConnect(nl);
1958
1959
1960         _endthread();
1961         return;
1962
1963 }
1964
1965 static void NicoLiveSelfDisconnect(void *buf){
1966
1967         NicoLiveStream_P nl = (NicoLiveStream_P)buf;
1968
1969         dumpln(TEXT("selfdisconnect"),);
1970
1971         NicoLiveStream_disConnect(nl);
1972
1973         _heapmin();
1974
1975
1976         _endthread();
1977         return;
1978
1979 }
1980
1981 static INLINE SOCKET GetConectedSocket(LPCTSTR nordName,LPCTSTR port,int socktype,int addr_famiry,int protocol){
1982
1983
1984         SOCKET rslt = INVALID_SOCKET;
1985
1986
1987         PADDRINFOW res,res0;
1988         ADDRINFOW hints;
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);
1994
1995
1996         for(res = res0; res != NULL;res = res->ai_next){
1997
1998
1999
2000
2001                 rslt = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
2002                 if(rslt == INVALID_SOCKET){
2003
2004                         continue;
2005                 }
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015                 if(connect(rslt,res->ai_addr,(int)res->ai_addrlen) == SOCKET_ERROR){
2016                         closesocket(rslt);
2017                         continue;
2018                 }
2019
2020
2021
2022
2023
2024
2025                 break;
2026
2027         }
2028
2029         if(res == NULL){
2030                 rslt = INVALID_SOCKET;
2031         }
2032
2033
2034         //res\8d\\91¢\91Ì\89ð\95ú
2035         FreeAddrInfo(res0);
2036
2037
2038         return rslt;
2039
2040 }
2041
2042
2043 //
2044 //\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\8aÖ\98A
2045 //
2046
2047 ///
2048 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82ÌID\82ð\8eæ\93¾
2049 ///
2050 NLIB_DECLSPEC LPCTSTR StreamStatus_getId(StreamStatus_P self){
2051
2052         return self->id;
2053 }
2054
2055
2056 ///
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¾
2058 ///
2059 NLIB_DECLSPEC LPCTSTR StreamStatus_getDefaultCommunity(StreamStatus_P self){
2060
2061         return self->default_community;
2062 }
2063
2064
2065 ///
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¾
2067 ///
2068 PROVIDERTYPE StreamStatus_getProviderType(StreamStatus_P self){
2069
2070         return self->provider_type;
2071 }
2072
2073
2074 ///
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¾
2076 ///
2077 BOOL StreamStatus_isOwner(StreamStatus_P self){
2078
2079         return self->is_owner;
2080 }
2081
2082 ///
2083 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82Ì\8aJ\8en\8e\9e\8d\8f\82ð\8eæ\93¾
2084 ///
2085 time_t StreamStatus_getStartTime(StreamStatus_P self){
2086
2087         return self->start_time;
2088 }
2089
2090 ///
2091 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82Ì\8fI\97¹\8e\9e\8d\8f\82ð\8eæ\93¾
2092 ///
2093 time_t StreamStatus_getEndTime(StreamStatus_P self){
2094
2095         return self->end_time;
2096 }
2097
2098 ///
2099 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82Ì\8aJ\8fê\8e\9e\8d\8f\82ð\8eæ\93¾
2100 ///
2101 time_t StreamStatus_getOpenTime(StreamStatus_P self){
2102
2103         return self->open_time;
2104
2105 }
2106
2107 ///
2108 ///\83X\83g\83\8a\81[\83\80\83X\83e\81[\83^\83X\82Ì\83x\81[\83X\8e\9e\8d\8f\82ð\8eæ\93¾
2109 ///
2110 time_t StreamStatus_getBaseTime(StreamStatus_P self){
2111
2112         return self->base_time;
2113 }