* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Connection.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // Connection.c\r
79 // コネクションマネージャ\r
80 \r
81 #include "CedarPch.h"\r
82 \r
83 // 送信に使用するかどうかの判別\r
84 #define IS_SEND_TCP_SOCK(ts)            \\r
85         ((ts->Direction == TCP_BOTH) || ((ts->Direction == TCP_SERVER_TO_CLIENT) && (s->ServerMode)) || ((ts->Direction == TCP_CLIENT_TO_SERVER) && (s->ServerMode == false)))\r
86 \r
87 // 受信に使用するかどうかの判別\r
88 #define IS_RECV_TCP_SOCK(ts)            \\r
89         ((ts->Direction == TCP_BOTH) || ((ts->Direction == TCP_SERVER_TO_CLIENT) && (s->ServerMode == false)) || ((ts->Direction == TCP_CLIENT_TO_SERVER) && (s->ServerMode)))\r
90 \r
91 // SECURE_SIGN の変換\r
92 void InRpcSecureSign(SECURE_SIGN *t, PACK *p)\r
93 {\r
94         // 引数チェック\r
95         if (t == NULL || p == NULL)\r
96         {\r
97                 return;\r
98         }\r
99 \r
100         Zero(t, sizeof(SECURE_SIGN));\r
101         PackGetStr(p, "SecurePublicCertName", t->SecurePublicCertName, sizeof(t->SecurePublicCertName));\r
102         PackGetStr(p, "SecurePrivateKeyName", t->SecurePrivateKeyName, sizeof(t->SecurePrivateKeyName));\r
103         t->ClientCert = PackGetX(p, "ClientCert");\r
104         PackGetData2(p, "Random", t->Random, sizeof(t->Random));\r
105         PackGetData2(p, "Signature", t->Signature, sizeof(t->Signature));\r
106         t->UseSecureDeviceId = PackGetInt(p, "UseSecureDeviceId");\r
107         t->BitmapId = PackGetInt(p, "BitmapId");\r
108 }\r
109 void OutRpcSecureSign(PACK *p, SECURE_SIGN *t)\r
110 {\r
111         // 引数チェック\r
112         if (p == NULL || t == NULL)\r
113         {\r
114                 return;\r
115         }\r
116 \r
117         PackAddStr(p, "SecurePublicCertName", t->SecurePublicCertName);\r
118         PackAddStr(p, "SecurePrivateKeyName", t->SecurePrivateKeyName);\r
119         PackAddX(p, "ClientCert", t->ClientCert);\r
120         PackAddData(p, "Random", t->Random, sizeof(t->Random));\r
121         PackAddData(p, "Signature", t->Signature, sizeof(t->Signature));\r
122         PackAddInt(p, "UseSecureDeviceId", t->UseSecureDeviceId);\r
123         PackAddInt(p, "BitmapId", t->BitmapId);\r
124 }\r
125 void FreeRpcSecureSign(SECURE_SIGN *t)\r
126 {\r
127         // 引数チェック\r
128         if (t == NULL)\r
129         {\r
130                 return;\r
131         }\r
132 \r
133         FreeX(t->ClientCert);\r
134 }\r
135 \r
136 // 次のパケットを生成する\r
137 BUF *NewKeepPacket(bool server_mode)\r
138 {\r
139         BUF *b = NewBuf();\r
140         char *string = KEEP_ALIVE_STRING;\r
141 \r
142         WriteBuf(b, string, StrLen(string));\r
143 \r
144         SeekBuf(b, 0, 0);\r
145 \r
146         return b;\r
147 }\r
148 \r
149 // KEEP スレッド\r
150 void KeepThread(THREAD *thread, void *param)\r
151 {\r
152         KEEP *k = (KEEP *)param;\r
153         SOCK *s;\r
154         char server_name[MAX_HOST_NAME_LEN + 1];\r
155         UINT server_port;\r
156         bool udp_mode;\r
157         bool enabled;\r
158         // 引数チェック\r
159         if (thread == NULL || k == NULL)\r
160         {\r
161                 return;\r
162         }\r
163 \r
164 WAIT_FOR_ENABLE:\r
165         Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);\r
166 \r
167         // 有効になるまで待機する\r
168         while (true)\r
169         {\r
170                 enabled = false;\r
171                 Lock(k->lock);\r
172                 {\r
173                         if (k->Enable)\r
174                         {\r
175                                 if (StrLen(k->ServerName) != 0 && k->ServerPort != 0 && k->Interval != 0)\r
176                                 {\r
177                                         StrCpy(server_name, sizeof(server_name), k->ServerName);\r
178                                         server_port = k->ServerPort;\r
179                                         udp_mode = k->UdpMode;\r
180                                         enabled = true;\r
181                                 }\r
182                         }\r
183                 }\r
184                 Unlock(k->lock);\r
185                 if (enabled)\r
186                 {\r
187                         break;\r
188                 }\r
189                 if (k->Halt)\r
190                 {\r
191                         return;\r
192                 }\r
193                 Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);\r
194         }\r
195 \r
196         if (udp_mode == false)\r
197         {\r
198                 // TCP モード\r
199                 // 接続に成功するまで試行する\r
200                 while (true)\r
201                 {\r
202                         UINT64 connect_started_tick;\r
203                         bool changed = false;\r
204                         Lock(k->lock);\r
205                         {\r
206                                 if (StrCmpi(k->ServerName, server_name) != 0 ||\r
207                                         k->ServerPort != server_port || k->Enable == false ||\r
208                                         k->UdpMode)\r
209                                 {\r
210                                         changed = true;\r
211                                 }\r
212                         }\r
213                         Unlock(k->lock);\r
214                         if (changed)\r
215                         {\r
216                                 // 設定が変更された\r
217                                 goto WAIT_FOR_ENABLE;\r
218                         }\r
219 \r
220                         if (k->Halt)\r
221                         {\r
222                                 // 停止\r
223                                 return;\r
224                         }\r
225 \r
226                         // サーバーへ接続を試行\r
227                         connect_started_tick = Tick64();\r
228                         s = ConnectEx2(server_name, server_port, KEEP_TCP_TIMEOUT, (bool *)&k->Halt);\r
229                         if (s != NULL)\r
230                         {\r
231                                 // 接続成功\r
232                                 break;\r
233                         }\r
234 \r
235                         // 接続失敗 設定が変更されるかタイムアウトするまで待機する\r
236                         while (true)\r
237                         {\r
238                                 changed = false;\r
239                                 if (k->Halt)\r
240                                 {\r
241                                         // 停止\r
242                                         return;\r
243                                 }\r
244                                 Lock(k->lock);\r
245                                 {\r
246                                         if (StrCmpi(k->ServerName, server_name) != 0 ||\r
247                                                 k->ServerPort != server_port || k->Enable == false ||\r
248                                                 k->UdpMode)\r
249                                         {\r
250                                                 changed = true;\r
251                                         }\r
252                                 }\r
253                                 Unlock(k->lock);\r
254 \r
255                                 if (changed)\r
256                                 {\r
257                                         // 設定が変更された\r
258                                         goto WAIT_FOR_ENABLE;\r
259                                 }\r
260 \r
261                                 if ((Tick64() - connect_started_tick) >= KEEP_RETRY_INTERVAL)\r
262                                 {\r
263                                         break;\r
264                                 }\r
265 \r
266                                 Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);\r
267                         }\r
268                 }\r
269 \r
270                 // サーバーへの接続に成功した\r
271                 // 一定時間ごとにパケットデータを送受信する\r
272                 if (s != NULL)\r
273                 {\r
274                         UINT64 last_packet_sent_time = 0;\r
275                         while (true)\r
276                         {\r
277                                 SOCKSET set;\r
278                                 UINT ret;\r
279                                 UCHAR buf[MAX_SIZE];\r
280                                 bool changed;\r
281 \r
282                                 InitSockSet(&set);\r
283                                 AddSockSet(&set, s);\r
284 \r
285                                 Select(&set, KEEP_POLLING_INTERVAL, k->Cancel, NULL);\r
286 \r
287                                 ret = Recv(s, buf, sizeof(buf), false);\r
288                                 if (ret == 0)\r
289                                 {\r
290                                         // 切断された\r
291                                         Disconnect(s);\r
292                                         ReleaseSock(s);\r
293                                         s = NULL;\r
294                                 }\r
295 \r
296                                 if (s != NULL)\r
297                                 {\r
298                                         if ((Tick64() - last_packet_sent_time) >= (UINT64)k->Interval)\r
299                                         {\r
300                                                 BUF *b;\r
301 \r
302                                                 // 次のパケットを送出する\r
303                                                 last_packet_sent_time = Tick64();\r
304 \r
305                                                 b = NewKeepPacket(k->Server);\r
306 \r
307                                                 ret = Send(s, b->Buf, b->Size, false);\r
308                                                 FreeBuf(b);\r
309 \r
310                                                 if (ret == 0)\r
311                                                 {\r
312                                                         // 切断された\r
313                                                         Disconnect(s);\r
314                                                         ReleaseSock(s);\r
315                                                         s = NULL;\r
316                                                 }\r
317                                         }\r
318                                 }\r
319 \r
320                                 changed = false;\r
321 \r
322                                 Lock(k->lock);\r
323                                 {\r
324                                         if (StrCmpi(k->ServerName, server_name) != 0 ||\r
325                                                 k->ServerPort != server_port || k->Enable == false ||\r
326                                                 k->UdpMode)\r
327                                         {\r
328                                                 changed = true;\r
329                                         }\r
330                                 }\r
331                                 Unlock(k->lock);\r
332 \r
333                                 if (changed || s == NULL)\r
334                                 {\r
335                                         // 設定が変更された または 切断された\r
336                                         Disconnect(s);\r
337                                         ReleaseSock(s);\r
338                                         s = NULL;\r
339                                         goto WAIT_FOR_ENABLE;\r
340                                 }\r
341                                 else\r
342                                 {\r
343                                         if (k->Halt)\r
344                                         {\r
345                                                 // 停止\r
346                                                 Disconnect(s);\r
347                                                 ReleaseSock(s);\r
348                                                 return;\r
349                                         }\r
350                                 }\r
351                         }\r
352                 }\r
353         }\r
354         else\r
355         {\r
356                 IP dest_ip;\r
357                 // UDP モード\r
358                 // ソケット作成が成功するまで試行する\r
359                 while (true)\r
360                 {\r
361                         UINT64 connect_started_tick;\r
362                         bool changed = false;\r
363                         Lock(k->lock);\r
364                         {\r
365                                 if (StrCmpi(k->ServerName, server_name) != 0 ||\r
366                                         k->ServerPort != server_port || k->Enable == false ||\r
367                                         k->UdpMode == false)\r
368                                 {\r
369                                         changed = true;\r
370                                 }\r
371                         }\r
372                         Unlock(k->lock);\r
373                         if (changed)\r
374                         {\r
375                                 // 設定が変更された\r
376                                 goto WAIT_FOR_ENABLE;\r
377                         }\r
378 \r
379                         if (k->Halt)\r
380                         {\r
381                                 // 停止\r
382                                 return;\r
383                         }\r
384 \r
385                         // ソケット作成を試行\r
386                         connect_started_tick = Tick64();\r
387 \r
388                         // まず名前解決を試行\r
389                         if (GetIP(&dest_ip, server_name))\r
390                         {\r
391                                 // 名前解決に成功したら、次にソケットを作成\r
392                                 s = NewUDP(0);\r
393                                 if (s != NULL)\r
394                                 {\r
395                                         // 作成成功\r
396                                         break;\r
397                                 }\r
398                         }\r
399 \r
400                         // 作成失敗 設定が変更されるかタイムアウトするまで待機する\r
401                         while (true)\r
402                         {\r
403                                 changed = false;\r
404                                 if (k->Halt)\r
405                                 {\r
406                                         // 停止\r
407                                         return;\r
408                                 }\r
409                                 Lock(k->lock);\r
410                                 {\r
411                                         if (StrCmpi(k->ServerName, server_name) != 0 ||\r
412                                                 k->ServerPort != server_port || k->Enable == false ||\r
413                                                 k->UdpMode)\r
414                                         {\r
415                                                 changed = true;\r
416                                         }\r
417                                 }\r
418                                 Unlock(k->lock);\r
419 \r
420                                 if (changed)\r
421                                 {\r
422                                         // 設定が変更された\r
423                                         goto WAIT_FOR_ENABLE;\r
424                                 }\r
425 \r
426                                 if ((Tick64() - connect_started_tick) >= KEEP_RETRY_INTERVAL)\r
427                                 {\r
428                                         break;\r
429                                 }\r
430 \r
431                                 Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);\r
432                         }\r
433                 }\r
434 \r
435                 // 一定時間ごとにパケットデータを送信する\r
436                 if (s != NULL)\r
437                 {\r
438                         UINT64 last_packet_sent_time = 0;\r
439                         while (true)\r
440                         {\r
441                                 SOCKSET set;\r
442                                 UINT ret;\r
443                                 UCHAR buf[MAX_SIZE];\r
444                                 bool changed;\r
445                                 IP src_ip;\r
446                                 UINT src_port;\r
447 \r
448                                 InitSockSet(&set);\r
449                                 AddSockSet(&set, s);\r
450 \r
451                                 Select(&set, KEEP_POLLING_INTERVAL, k->Cancel, NULL);\r
452 \r
453                                 // 受信\r
454                                 ret = RecvFrom(s, &src_ip, &src_port, buf, sizeof(buf));\r
455                                 if (ret == 0 && s->IgnoreRecvErr == false)\r
456                                 {\r
457                                         // 切断された\r
458                                         Disconnect(s);\r
459                                         ReleaseSock(s);\r
460                                         s = NULL;\r
461                                 }\r
462 \r
463                                 if (s != NULL)\r
464                                 {\r
465                                         if ((Tick64() - last_packet_sent_time) >= (UINT64)k->Interval)\r
466                                         {\r
467                                                 BUF *b;\r
468 \r
469                                                 // 次のパケットを送出する\r
470                                                 last_packet_sent_time = Tick64();\r
471 \r
472                                                 b = NewKeepPacket(k->Server);\r
473 \r
474                                                 ret = SendTo(s, &dest_ip, server_port, b->Buf, b->Size);\r
475                                                 FreeBuf(b);\r
476 \r
477                                                 if (ret == 0 && s->IgnoreSendErr == false)\r
478                                                 {\r
479                                                         // 切断された\r
480                                                         Disconnect(s);\r
481                                                         ReleaseSock(s);\r
482                                                         s = NULL;\r
483                                                 }\r
484                                         }\r
485                                 }\r
486 \r
487                                 changed = false;\r
488 \r
489                                 Lock(k->lock);\r
490                                 {\r
491                                         if (StrCmpi(k->ServerName, server_name) != 0 ||\r
492                                                 k->ServerPort != server_port || k->Enable == false ||\r
493                                                 k->UdpMode == false)\r
494                                         {\r
495                                                 changed = true;\r
496                                         }\r
497                                 }\r
498                                 Unlock(k->lock);\r
499 \r
500                                 if (changed || s == NULL)\r
501                                 {\r
502                                         // 設定が変更された または 切断された\r
503                                         Disconnect(s);\r
504                                         ReleaseSock(s);\r
505                                         s = NULL;\r
506                                         goto WAIT_FOR_ENABLE;\r
507                                 }\r
508                                 else\r
509                                 {\r
510                                         if (k->Halt)\r
511                                         {\r
512                                                 // 停止\r
513                                                 Disconnect(s);\r
514                                                 ReleaseSock(s);\r
515                                                 return;\r
516                                         }\r
517                                 }\r
518                         }\r
519                 }\r
520         }\r
521 }\r
522 \r
523 // KEEP 停止\r
524 void StopKeep(KEEP *k)\r
525 {\r
526         // 引数チェック\r
527         if (k == NULL)\r
528         {\r
529                 return;\r
530         }\r
531 \r
532         k->Halt = true;\r
533         Set(k->HaltEvent);\r
534         Cancel(k->Cancel);\r
535 \r
536         WaitThread(k->Thread, INFINITE);\r
537         ReleaseThread(k->Thread);\r
538         DeleteLock(k->lock);\r
539 \r
540         ReleaseCancel(k->Cancel);\r
541         ReleaseEvent(k->HaltEvent);\r
542 \r
543         Free(k);\r
544 }\r
545 \r
546 // KEEP 開始\r
547 KEEP *StartKeep()\r
548 {\r
549         KEEP *k = ZeroMalloc(sizeof(KEEP));\r
550 \r
551         k->lock = NewLock();\r
552         k->HaltEvent = NewEvent();\r
553         k->Cancel = NewCancel();\r
554 \r
555         // スレッド開始\r
556         k->Thread = NewThread(KeepThread, k);\r
557 \r
558         return k;\r
559 }\r
560 \r
561 // クライアント認証データのコピー\r
562 CLIENT_AUTH *CopyClientAuth(CLIENT_AUTH *a)\r
563 {\r
564         CLIENT_AUTH *ret;\r
565         // 引数チェック\r
566         if (a == NULL)\r
567         {\r
568                 return NULL;\r
569         }\r
570 \r
571         ret = ZeroMallocEx(sizeof(CLIENT_AUTH), true);\r
572 \r
573         ret->AuthType = a->AuthType;\r
574         StrCpy(ret->Username, sizeof(ret->Username), a->Username);\r
575 \r
576         switch (a->AuthType)\r
577         {\r
578         case CLIENT_AUTHTYPE_ANONYMOUS:\r
579                 // 匿名認証\r
580                 break;\r
581 \r
582         case CLIENT_AUTHTYPE_PASSWORD:\r
583                 // パスワード認証\r
584                 Copy(ret->HashedPassword, a->HashedPassword, SHA1_SIZE);\r
585                 break;\r
586 \r
587         case CLIENT_AUTHTYPE_PLAIN_PASSWORD:\r
588                 // 平文パスワード認証\r
589                 StrCpy(ret->PlainPassword, sizeof(ret->PlainPassword), a->PlainPassword);\r
590                 break;\r
591 \r
592         case CLIENT_AUTHTYPE_CERT:\r
593                 // 証明書認証\r
594                 ret->ClientX = CloneX(a->ClientX);\r
595                 ret->ClientK = CloneK(a->ClientK);\r
596                 break;\r
597 \r
598         case CLIENT_AUTHTYPE_SECURE:\r
599                 // セキュアデバイス認証\r
600                 StrCpy(ret->SecurePublicCertName, sizeof(ret->SecurePublicCertName), a->SecurePublicCertName);\r
601                 StrCpy(ret->SecurePrivateKeyName, sizeof(ret->SecurePrivateKeyName), a->SecurePrivateKeyName);\r
602                 break;\r
603         }\r
604 \r
605         return ret;\r
606 }\r
607 \r
608 // 送信 FIFO にデータを書き込む (自動暗号化)\r
609 void WriteSendFifo(SESSION *s, TCPSOCK *ts, void *data, UINT size)\r
610 {\r
611         // 引数チェック\r
612         if (s == NULL || ts == NULL || data == NULL)\r
613         {\r
614                 return;\r
615         }\r
616 \r
617         if (s->UseFastRC4)\r
618         {\r
619                 Encrypt(ts->SendKey, data, data, size);\r
620         }\r
621 \r
622         WriteFifo(ts->SendFifo, data, size);\r
623 }\r
624 \r
625 // 受信 FIFO にデータを書き込む (自動解読)\r
626 void WriteRecvFifo(SESSION *s, TCPSOCK *ts, void *data, UINT size)\r
627 {\r
628         // 引数チェック\r
629         if (s == NULL || ts == NULL || data == NULL)\r
630         {\r
631                 return;\r
632         }\r
633 \r
634         if (s->UseFastRC4)\r
635         {\r
636                 Encrypt(ts->RecvKey, data, data, size);\r
637         }\r
638 \r
639         WriteFifo(ts->RecvFifo, data, size);\r
640 }\r
641 \r
642 // TCP ソケット受信\r
643 UINT TcpSockRecv(SESSION *s, TCPSOCK *ts, void *data, UINT size)\r
644 {\r
645         // 受信\r
646         return Recv(ts->Sock, data, size, s->UseSSLDataEncryption);\r
647 }\r
648 \r
649 // TCP ソケット送信\r
650 UINT TcpSockSend(SESSION *s, TCPSOCK *ts, void *data, UINT size)\r
651 {\r
652         // 送信\r
653         return Send(ts->Sock, data, size, s->UseSSLDataEncryption);\r
654 }\r
655 \r
656 // データを UDP パケットとして送信する\r
657 void SendDataWithUDP(SOCK *s, CONNECTION *c)\r
658 {\r
659         UCHAR *buf;\r
660         BUF *b;\r
661         UINT64 dummy_64 = 0;\r
662         UCHAR dummy_buf[16];\r
663         UINT64 now = Tick64();\r
664         UINT ret;\r
665         bool force_flag = false;\r
666         bool packet_sent = false;\r
667         // 引数チェック\r
668         if (s == NULL || c == NULL)\r
669         {\r
670                 return;\r
671         }\r
672 \r
673         // 一時バッファをヒープから確保しておく\r
674         if (c->RecvBuf == NULL)\r
675         {\r
676                 c->RecvBuf = Malloc(RECV_BUF_SIZE);\r
677         }\r
678         buf = c->RecvBuf;\r
679 \r
680         if (c->Udp->NextKeepAliveTime == 0 || c->Udp->NextKeepAliveTime <= now)\r
681         {\r
682                 force_flag = true;\r
683         }\r
684 \r
685         // バッファの作成\r
686         while ((c->SendBlocks->num_item > 0) || force_flag)\r
687         {\r
688                 UINT *key32;\r
689                 UINT64 *seq;\r
690                 char *sign;\r
691 \r
692                 force_flag = false;\r
693 \r
694                 // 現在のキューからバッファを組み立てる\r
695                 b = NewBuf();\r
696 \r
697                 // パケットヘッダ (16バイト) 分の領域を確保\r
698                 WriteBuf(b, dummy_buf, sizeof(dummy_buf));\r
699 \r
700                 // 送信キューのパケットを詰め込む\r
701                 LockQueue(c->SendBlocks);\r
702                 {\r
703                         while (true)\r
704                         {\r
705                                 BLOCK *block;\r
706 \r
707                                 if (b->Size > UDP_BUF_SIZE)\r
708                                 {\r
709                                         break;\r
710                                 }\r
711                                 block = GetNext(c->SendBlocks);\r
712                                 if (block == NULL)\r
713                                 {\r
714                                         break;\r
715                                 }\r
716 \r
717                                 if (block->Size != 0)\r
718                                 {\r
719                                         WriteBufInt(b, block->Size);\r
720                                         WriteBuf(b, block->Buf, block->Size);\r
721 \r
722                                         c->Session->TotalSendSize += (UINT64)block->SizeofData;\r
723                                         c->Session->TotalSendSizeReal += (UINT64)block->Size;\r
724                                 }\r
725 \r
726                                 FreeBlock(block);\r
727                                 break;\r
728                         }\r
729                 }\r
730                 UnlockQueue(c->SendBlocks);\r
731 \r
732                 // セッションキーとシーケンス番号の書き込み\r
733                 sign = (char *)(((UCHAR *)b->Buf));\r
734                 key32 = (UINT *)(((UCHAR *)b->Buf + 4));\r
735                 seq = (UINT64 *)(((UCHAR *)b->Buf + 8));\r
736                 Copy(sign, SE_UDP_SIGN, 4);\r
737                 *key32 = Endian32(c->Session->SessionKey32);\r
738                 *seq = Endian64(c->Udp->Seq++); // シーケンス番号をインクリメントする\r
739 \r
740 //              InsertQueue(c->Udp->BufferQueue, b);\r
741 \r
742                 packet_sent = true;\r
743 /*      }\r
744 \r
745         // バッファの送信\r
746         while (c->Udp->BufferQueue->num_item != 0)\r
747         {\r
748                 FIFO *f = c->Udp->BufferQueue->fifo;\r
749                 BUF **pb = (BUF**)(((UCHAR *)f->p) + f->pos);\r
750                 BUF *b = *pb;\r
751 \r
752 */              ret = SendTo(s, &c->Udp->ip, c->Udp->port, b->Buf, b->Size);\r
753                 if (ret == SOCK_LATER)\r
754                 {\r
755                         // ブロッキング\r
756                         Debug(".");\r
757 //                      break;\r
758                 }\r
759                 if (ret != b->Size)\r
760                 {\r
761                         if (s->IgnoreSendErr == false)\r
762                         {\r
763                                 // エラー\r
764                                 Debug("******* SendTo Error !!!\n");\r
765                         }\r
766                 }\r
767 \r
768                 // メモリ解放\r
769                 FreeBuf(b);\r
770 //              GetNext(c->Udp->BufferQueue);\r
771         }\r
772 \r
773         if (packet_sent)\r
774         {\r
775                 // KeepAlive 時刻更新\r
776                 c->Udp->NextKeepAliveTime = now + (UINT64)GenNextKeepAliveSpan(c);\r
777         }\r
778 }\r
779 \r
780 // UDP パケットのデータをコネクションに書き込む\r
781 void PutUDPPacketData(CONNECTION *c, void *data, UINT size)\r
782 {\r
783         BUF *b;\r
784         char sign[4];\r
785         // 引数チェック\r
786         if (c == NULL || data == NULL)\r
787         {\r
788                 return;\r
789         }\r
790 \r
791         // プロトコルを調べる\r
792         if (c->Protocol != CONNECTION_UDP)\r
793         {\r
794                 // UDP プロトコルは利用されていない\r
795                 return;\r
796         }\r
797 \r
798         // バッファ構成\r
799         b = NewBuf();\r
800         WriteBuf(b, data, size);\r
801 \r
802         SeekBuf(b, 0, 0);\r
803         ReadBuf(b, sign, 4);\r
804 \r
805         // サイン確認\r
806         if (Cmp(sign, SE_UDP_SIGN, 4) == 0)\r
807         {\r
808                 UINT key32;\r
809 \r
810                 // セッションキー番号\r
811                 key32 = ReadBufInt(b);\r
812 \r
813                 if (c->Session->SessionKey32 == key32)\r
814                 {\r
815                         UINT64 seq;\r
816 \r
817                         // シーケンス番号読み込み\r
818                         ReadBuf(b, &seq, sizeof(seq));\r
819                         seq = Endian64(seq);\r
820 \r
821                         if ((UINT)(seq - c->Udp->RecvSeq - (UINT64)1))\r
822                         {\r
823                                 //Debug("** UDP Seq Lost %u\n", (UINT)(seq - c->Udp->RecvSeq - (UINT64)1));\r
824                         }\r
825                         c->Udp->RecvSeq = seq;\r
826 \r
827                         //Debug("SEQ: %I32u\n", seq);\r
828 \r
829                         while (true)\r
830                         {\r
831                                 UINT size;\r
832 \r
833                                 size = ReadBufInt(b);\r
834                                 if (size == 0)\r
835                                 {\r
836                                         break;\r
837                                 }\r
838                                 else if (size <= MAX_PACKET_SIZE)\r
839                                 {\r
840                                         void *tmp;\r
841                                         BLOCK *block;\r
842 \r
843                                         tmp = Malloc(size);\r
844                                         if (ReadBuf(b, tmp, size) != size)\r
845                                         {\r
846                                                 Free(tmp);\r
847                                                 break;\r
848                                         }\r
849 \r
850                                         // ブロック構成\r
851                                         block = NewBlock(tmp, size, 0);\r
852 \r
853                                         // ブロック挿入\r
854                                         InsertReveicedBlockToQueue(c, block);\r
855                                 }\r
856                         }\r
857 \r
858                         // 最終通信時刻を更新\r
859                         c->Session->LastCommTime = Tick64();\r
860                 }\r
861                 else\r
862                 {\r
863                         Debug("Invalid SessionKey: 0x%X\n", key32);\r
864                 }\r
865         }\r
866 \r
867         FreeBuf(b);\r
868 }\r
869 \r
870 // 受信キューにブロックを追加する\r
871 void InsertReveicedBlockToQueue(CONNECTION *c, BLOCK *block)\r
872 {\r
873         SESSION *s;\r
874         // 引数チェック\r
875         if (c == NULL || block == NULL)\r
876         {\r
877                 return;\r
878         }\r
879 \r
880         s = c->Session;\r
881         \r
882         if (c->Protocol == CONNECTION_TCP)\r
883         {\r
884                 s->TotalRecvSizeReal += block->SizeofData;\r
885                 s->TotalRecvSize += block->Size;\r
886         }\r
887 \r
888         LockQueue(c->ReceivedBlocks);\r
889         {\r
890                 InsertQueue(c->ReceivedBlocks, block);\r
891         }\r
892         UnlockQueue(c->ReceivedBlocks);\r
893 }\r
894 \r
895 // 次の Keep-Alive パケットまでの間隔を生成 (ネットワーク負荷減少のため乱数にする)\r
896 UINT GenNextKeepAliveSpan(CONNECTION *c)\r
897 {\r
898         UINT a, b;\r
899         // 引数チェック\r
900         if (c == NULL)\r
901         {\r
902                 return INFINITE;\r
903         }\r
904 \r
905         a = c->Session->Timeout;\r
906         b = rand() % (a / 2);\r
907         b = MAX(b, a / 5);\r
908 \r
909         return b;\r
910 }\r
911 \r
912 // Keep-Alive パケットを送信する\r
913 void SendKeepAlive(CONNECTION *c, TCPSOCK *ts)\r
914 {\r
915         UINT size, i, num;\r
916         UINT size_be;\r
917         UCHAR *buf;\r
918         // 引数チェック\r
919         if (c == NULL || ts == NULL)\r
920         {\r
921                 return;\r
922         }\r
923 \r
924         size = rand() % MAX_KEEPALIVE_SIZE;\r
925         num = KEEP_ALIVE_MAGIC;\r
926         buf = MallocFast(size);\r
927 \r
928         for (i = 0;i < size;i++)\r
929         {\r
930                 buf[i] = rand();\r
931         }\r
932 \r
933         num = Endian32(num);\r
934         size_be = Endian32(size);\r
935         WriteSendFifo(c->Session, ts, &num, sizeof(UINT));\r
936         WriteSendFifo(c->Session, ts, &size_be, sizeof(UINT));\r
937         WriteSendFifo(c->Session, ts, buf, size);\r
938 \r
939         c->Session->TotalSendSize += sizeof(UINT) * 2 + size;\r
940         c->Session->TotalSendSizeReal += sizeof(UINT) * 2 + size;\r
941 \r
942         Free(buf);\r
943 }\r
944 \r
945 // ブロックの送信\r
946 void ConnectionSend(CONNECTION *c)\r
947 {\r
948         // このあたりは急いで実装したのでコードがあまり美しくない。\r
949         UINT i, num;\r
950         UINT64 now;\r
951         UINT min_count;\r
952         TCPSOCK **tcpsocks;\r
953         UINT size;\r
954         SESSION *s;\r
955         bool use_qos;\r
956         // 引数チェック\r
957         if (c == NULL)\r
958         {\r
959                 return;\r
960         }\r
961 \r
962         s = c->Session;\r
963         use_qos = s->QoS;\r
964 \r
965         now = Tick64();\r
966 \r
967         // プロトコル\r
968         if (c->Protocol == CONNECTION_TCP)\r
969         {\r
970                 // TCP\r
971                 TCP *tcp = c->Tcp;\r
972                 TCPSOCK *ts;\r
973                 TCPSOCK *ts_hp;\r
974                 UINT num_available;\r
975                 LockList(tcp->TcpSockList);\r
976                 {\r
977                         num = LIST_NUM(tcp->TcpSockList);\r
978                         tcpsocks = ToArrayEx(tcp->TcpSockList, true);\r
979                 }\r
980                 UnlockList(tcp->TcpSockList);\r
981 \r
982                 // 送信に使用するソケットを選択する\r
983                 // 遅延回数が最も少ないソケットを選出\r
984                 min_count = INFINITE;\r
985                 ts = NULL;\r
986                 ts_hp = NULL;\r
987 \r
988                 num_available = 0;\r
989 \r
990                 for (i = 0;i < num;i++)\r
991                 {\r
992                         TCPSOCK *tcpsock = tcpsocks[i];\r
993                         if (tcpsock->Sock->Connected && tcpsock->Sock->AsyncMode &&\r
994                                 IS_SEND_TCP_SOCK(tcpsock))\r
995                         {\r
996                                 // KeepAlive の処理\r
997                                 if (now >= tcpsock->NextKeepAliveTime || tcpsock->NextKeepAliveTime == 0)\r
998                                 {\r
999                                         // KeepAlive を打つ\r
1000                                         SendKeepAlive(c, tcpsock);\r
1001                                         tcpsock->NextKeepAliveTime = now + (UINT64)GenNextKeepAliveSpan(c);\r
1002                                 }\r
1003 \r
1004                                 // 送信に利用可能なソケット数を計測する\r
1005                                 num_available++;\r
1006 \r
1007                                 ts_hp = tcpsock;\r
1008                         }\r
1009                 }\r
1010 \r
1011                 for (i = 0;i < num;i++)\r
1012                 {\r
1013                         TCPSOCK *tcpsock = tcpsocks[i];\r
1014                         if (tcpsock->Sock->Connected && tcpsock->Sock->AsyncMode &&\r
1015                                 IS_SEND_TCP_SOCK(tcpsock))\r
1016                         {\r
1017                                 // ソケットの選出\r
1018                                 bool b = false;\r
1019 \r
1020                                 if (use_qos == false)\r
1021                                 {\r
1022                                         b = true;\r
1023                                 }\r
1024                                 else if (num_available < 2)\r
1025                                 {\r
1026                                         b = true;\r
1027                                 }\r
1028                                 else if (tcpsock != ts_hp)\r
1029                                 {\r
1030                                         b = true;\r
1031                                 }\r
1032 \r
1033                                 if (b)\r
1034                                 {\r
1035                                         if (tcpsock->LateCount <= min_count)\r
1036                                         {\r
1037                                                 min_count = tcpsock->LateCount;\r
1038                                                 ts = tcpsock;\r
1039                                         }\r
1040                                 }\r
1041                         }\r
1042                 }\r
1043 \r
1044                 if (use_qos == false)\r
1045                 {\r
1046                         ts_hp = ts;\r
1047                 }\r
1048 \r
1049                 if (ts == NULL || ts_hp == NULL)\r
1050                 {\r
1051                         // 現在 送信可能なソケットが存在しない\r
1052                 }\r
1053                 else\r
1054                 {\r
1055                         TCPSOCK *tss;\r
1056                         UINT j;\r
1057                         QUEUE *q;\r
1058 \r
1059                         for (j = 0;j < 2;j++)\r
1060                         {\r
1061                                 if (j == 0)\r
1062                                 {\r
1063                                         q = c->SendBlocks2;\r
1064                                         tss = ts_hp;\r
1065                                 }\r
1066                                 else\r
1067                                 {\r
1068                                         q = c->SendBlocks;\r
1069                                         tss = ts;\r
1070                                 }\r
1071                                 // 選択されたソケット ts に対して送信データを予約する\r
1072                                 LockQueue(c->SendBlocks);\r
1073                                 if (q->num_item != 0)\r
1074                                 {\r
1075                                         UINT num_data;\r
1076                                         BLOCK *b;\r
1077 \r
1078                                         if (tss->SendFifo->size >= MAX((MAX_SEND_SOCKET_QUEUE_SIZE / s->MaxConnection), MIN_SEND_SOCKET_QUEUE_SIZE))\r
1079                                         {\r
1080                                                 // 送信ソケットキューのサイズが超過\r
1081                                                 // 送信できない\r
1082                                                 while (b = GetNext(q))\r
1083                                                 {\r
1084                                                         if (b != NULL)\r
1085                                                         {\r
1086                                                                 c->CurrentSendQueueSize -= b->Size;\r
1087                                                                 FreeBlock(b);\r
1088                                                         }\r
1089                                                 }\r
1090                                         }\r
1091                                         else\r
1092                                         {\r
1093                                                 bool update_keepalive_timer = false;\r
1094                                                 // 個数データ\r
1095                                                 num_data = Endian32(q->num_item);\r
1096                                                 PROBE_DATA2("WriteSendFifo num", &num_data, sizeof(UINT));\r
1097                                                 WriteSendFifo(s, tss, &num_data, sizeof(UINT));\r
1098 \r
1099                                                 s->TotalSendSize += sizeof(UINT);\r
1100                                                 s->TotalSendSizeReal += sizeof(UINT);\r
1101 \r
1102                                                 while (b = GetNext(q))\r
1103                                                 {\r
1104                                                         // サイズデータ\r
1105                                                         UINT size_data;\r
1106                                                         size_data = Endian32(b->Size);\r
1107                                                         PROBE_DATA2("WriteSendFifo size", &size_data, sizeof(UINT));\r
1108                                                         WriteSendFifo(s, tss, &size_data, sizeof(UINT));\r
1109 \r
1110                                                         c->CurrentSendQueueSize -= b->Size;\r
1111 \r
1112                                                         s->TotalSendSize += sizeof(UINT);\r
1113                                                         s->TotalSendSizeReal += sizeof(UINT);\r
1114 \r
1115                                                         // データ本体\r
1116                                                         PROBE_DATA2("WriteSendFifo data", b->Buf, b->Size);\r
1117                                                         WriteSendFifo(s, tss, b->Buf, b->Size);\r
1118 \r
1119                                                         s->TotalSendSize += b->SizeofData;\r
1120                                                         s->TotalSendSizeReal += b->Size;\r
1121 \r
1122                                                         update_keepalive_timer = true;\r
1123 \r
1124                                                         // ブロック解放\r
1125                                                         FreeBlock(b);\r
1126                                                 }\r
1127 \r
1128                                                 if (update_keepalive_timer)\r
1129                                                 {\r
1130                                                         // KeepAlive タイマを増加させる\r
1131                                                         tss->NextKeepAliveTime = now + (UINT64)GenNextKeepAliveSpan(c);\r
1132                                                 }\r
1133                                         }\r
1134                                 }\r
1135                                 UnlockQueue(c->SendBlocks);\r
1136                         }\r
1137                 }\r
1138 \r
1139                 // 現在各ソケットに登録されている送信予約データを送信する\r
1140                 for (i = 0;i < num;i++)\r
1141                 {\r
1142                         ts = tcpsocks[i];\r
1143 \r
1144 SEND_START:\r
1145                         if (ts->Sock->Connected == false)\r
1146                         {\r
1147                                 s->LastTryAddConnectTime = Tick64();\r
1148                                 // 通信が切断された\r
1149                                 LockList(tcp->TcpSockList);\r
1150                                 {\r
1151                                         // ソケットリストからこのソケットを削除する\r
1152                                         Delete(tcp->TcpSockList, ts);\r
1153                                         // TCPSOCK の解放\r
1154                                         FreeTcpSock(ts);\r
1155                                         // 個数のデクリメント\r
1156                                         Dec(c->CurrentNumConnection);\r
1157                                         Debug("--- TCP Connection Decremented: %u (%s Line %u)\n", Count(c->CurrentNumConnection), __FILE__, __LINE__);\r
1158                                         Debug("LIST_NUM(tcp->TcpSockList): %u\n", LIST_NUM(tcp->TcpSockList));\r
1159                                 }\r
1160                                 UnlockList(tcp->TcpSockList);\r
1161 \r
1162                                 continue;\r
1163                         }\r
1164 \r
1165                         // Fifo サイズを取得\r
1166                         if (ts->SendFifo->size != 0)\r
1167                         {\r
1168                                 UCHAR *buf;\r
1169                                 UINT want_send_size;\r
1170                                 // 1 バイト以上送信予定データが存在する場合のみ送信する\r
1171                                 // バッファへのポインタを取得\r
1172                                 buf = (UCHAR *)ts->SendFifo->p + ts->SendFifo->pos;\r
1173                                 want_send_size = ts->SendFifo->size;\r
1174 \r
1175                                 PROBE_DATA2("TcpSockSend", buf, want_send_size);\r
1176                                 size = TcpSockSend(s, ts, buf, want_send_size);\r
1177                                 if (size == 0)\r
1178                                 {\r
1179                                         // 切断された\r
1180                                         continue;\r
1181                                 }\r
1182                                 else if (size == SOCK_LATER)\r
1183                                 {\r
1184                                         // パケットが詰まっている\r
1185                                         ts->LateCount++; // 遅延カウンタのインクリメント\r
1186                                         PROBE_STR("ts->LateCount++;");\r
1187                                 }\r
1188                                 else\r
1189                                 {\r
1190                                         // パケットが size だけ送信された\r
1191                                         // FIFO を進める\r
1192                                         ReadFifo(ts->SendFifo, NULL, size);\r
1193                                         if (size < want_send_size)\r
1194                                         {\r
1195                                                 // 予定されたデータのすべてを送信することができなかった\r
1196 #ifdef  USE_PROBE\r
1197                                                 {\r
1198                                                         char tmp[MAX_SIZE];\r
1199 \r
1200                                                         snprintf(tmp, sizeof(tmp), "size < want_send_size: %u < %u",\r
1201                                                                 size, want_send_size);\r
1202 \r
1203                                                         PROBE_STR(tmp);\r
1204                                                 }\r
1205 #endif  // USE_PROBE\r
1206                                         }\r
1207                                         else\r
1208                                         {\r
1209                                                 // すべてのパケットの送信が完了した (キューが無くなった)\r
1210                                                 // ので、遅延カウンタをリセットする\r
1211                                                 ts->LateCount = 0;\r
1212 \r
1213                                                 PROBE_STR("TcpSockSend All Completed");\r
1214                                         }\r
1215                                         // 最終通信日時を更新\r
1216                                         c->Session->LastCommTime = now;\r
1217 \r
1218                                         goto SEND_START;\r
1219                                 }\r
1220                         }\r
1221                 }\r
1222 \r
1223                 Free(tcpsocks);\r
1224         }\r
1225         else if (c->Protocol == CONNECTION_UDP)\r
1226         {\r
1227                 // UDP\r
1228                 UDP *udp = c->Udp;\r
1229                 SOCK *sock = NULL;\r
1230 \r
1231                 Lock(c->lock);\r
1232                 {\r
1233                         sock = udp->s;\r
1234                         if (sock != NULL)\r
1235                         {\r
1236                                 AddRef(sock->ref);\r
1237                         }\r
1238                 }\r
1239                 Unlock(c->lock);\r
1240 \r
1241                 if (sock != NULL)\r
1242                 {\r
1243                         // UDP で送信する\r
1244 \r
1245                         // KeepAlive 送信\r
1246                         if ((udp->NextKeepAliveTime == 0 || udp->NextKeepAliveTime <= now) ||\r
1247                                 (c->SendBlocks->num_item != 0) || (udp->BufferQueue->num_item != 0))\r
1248                         {\r
1249                                 // 現在のキューを UDP で送信\r
1250                                 SendDataWithUDP(sock, c);\r
1251                         }\r
1252                 }\r
1253 \r
1254                 if (sock != NULL)\r
1255                 {\r
1256                         ReleaseSock(sock);\r
1257                 }\r
1258         }\r
1259         else if (c->Protocol == CONNECTION_HUB_SECURE_NAT)\r
1260         {\r
1261                 // SecureNAT セッション\r
1262                 SNAT *snat = s->SecureNAT;\r
1263                 VH *v = snat->Nat->Virtual;\r
1264 \r
1265                 LockQueue(c->SendBlocks);\r
1266                 {\r
1267                         BLOCK *block;\r
1268                         UINT num_packet = 0;\r
1269 \r
1270                         while (block = GetNext(c->SendBlocks))\r
1271                         {\r
1272                                 num_packet++;\r
1273                                 c->CurrentSendQueueSize -= block->Size;\r
1274                                 VirtualPutPacket(v, block->Buf, block->Size);\r
1275                                 Free(block);\r
1276                         }\r
1277 \r
1278                         if (num_packet != 0)\r
1279                         {\r
1280                                 VirtualPutPacket(v, NULL, 0);\r
1281                         }\r
1282                 }\r
1283                 UnlockQueue(c->SendBlocks);\r
1284         }\r
1285         else if (c->Protocol == CONNECTION_HUB_LAYER3)\r
1286         {\r
1287                 // Layer-3 セッション\r
1288                 L3IF *f = s->L3If;\r
1289 \r
1290                 LockQueue(c->SendBlocks);\r
1291                 {\r
1292                         BLOCK *block;\r
1293                         UINT num_packet = 0;\r
1294 \r
1295                         while (block = GetNext(c->SendBlocks))\r
1296                         {\r
1297                                 num_packet++;\r
1298                                 c->CurrentSendQueueSize -= block->Size;\r
1299                                 L3PutPacket(f, block->Buf, block->Size);\r
1300                                 Free(block);\r
1301                         }\r
1302 \r
1303                         if (num_packet != 0)\r
1304                         {\r
1305                                 L3PutPacket(f, NULL, 0);\r
1306                         }\r
1307                 }\r
1308                 UnlockQueue(c->SendBlocks);\r
1309         }\r
1310         else if (c->Protocol == CONNECTION_HUB_LINK_SERVER)\r
1311         {\r
1312                 // HUB リンク\r
1313                 LINK *k = (LINK *)s->Link;\r
1314 \r
1315                 if (k != NULL)\r
1316                 {\r
1317                         LockQueue(c->SendBlocks);\r
1318                         {\r
1319                                 UINT num_blocks = 0;\r
1320                                 LockQueue(k->SendPacketQueue);\r
1321                                 {\r
1322                                         BLOCK *block;\r
1323 \r
1324                                         // パケットキューをクライアントスレッドに転送する\r
1325                                         while (block = GetNext(c->SendBlocks))\r
1326                                         {\r
1327                                                 num_blocks++;\r
1328                                                 c->CurrentSendQueueSize -= block->Size;\r
1329                                                 InsertQueue(k->SendPacketQueue, block);\r
1330                                         }\r
1331                                 }\r
1332                                 UnlockQueue(k->SendPacketQueue);\r
1333 \r
1334                                 if (num_blocks != 0)\r
1335                                 {\r
1336                                         // キャンセルの発行\r
1337                                         Cancel(k->ClientSession->Cancel1);\r
1338                                 }\r
1339                         }\r
1340                         UnlockQueue(c->SendBlocks);\r
1341                 }\r
1342         }\r
1343         else if (c->Protocol == CONNECTION_HUB_BRIDGE)\r
1344         {\r
1345                 // ローカルブリッジ\r
1346                 BRIDGE *b = s->Bridge;\r
1347 \r
1348                 if (b != NULL)\r
1349                 {\r
1350                         if (b->Active)\r
1351                         {\r
1352                                 LockQueue(c->SendBlocks);\r
1353                                 {\r
1354                                         BLOCK *block;\r
1355                                         UINT num_packet = c->SendBlocks->num_item; // パケット数\r
1356 \r
1357                                         if (num_packet != 0)\r
1358                                         {\r
1359                                                 // パケットデータ配列\r
1360                                                 void **datas = MallocFast(sizeof(void *) * num_packet);\r
1361                                                 UINT *sizes = MallocFast(sizeof(UINT *) * num_packet);\r
1362                                                 UINT i;\r
1363 \r
1364                                                 i = 0;\r
1365                                                 while (block = GetNext(c->SendBlocks))\r
1366                                                 {\r
1367                                                         datas[i] = block->Buf;\r
1368                                                         sizes[i] = block->Size;\r
1369 \r
1370                                                         if (block->Size > 1514)\r
1371                                                         {\r
1372                                                                 NormalizeEthMtu(b, c, block->Size);\r
1373                                                         }\r
1374 \r
1375                                                         c->CurrentSendQueueSize -= block->Size;\r
1376                                                         Free(block);\r
1377                                                         i++;\r
1378                                                 }\r
1379 \r
1380                                                 // パケットを書き込む\r
1381                                                 EthPutPackets(b->Eth, num_packet, datas, sizes);\r
1382 \r
1383                                                 Free(datas);\r
1384                                                 Free(sizes);\r
1385                                         }\r
1386                                 }\r
1387                                 UnlockQueue(c->SendBlocks);\r
1388                         }\r
1389                 }\r
1390         }\r
1391 }\r
1392 \r
1393 // ブロックの受信\r
1394 void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)\r
1395 {\r
1396         // このあたりは急いで実装したのでコードがあまり美しくない。\r
1397         UINT i, num;\r
1398         SOCKSET set;\r
1399         SESSION *s;\r
1400         TCPSOCK **tcpsocks;\r
1401         UCHAR *buf;\r
1402         UINT size;\r
1403         UINT64 now;\r
1404         UINT time;\r
1405         UINT num_delayed = 0;\r
1406         bool no_spinlock_for_delay = false;\r
1407         // 引数チェック\r
1408         if (c == NULL)\r
1409         {\r
1410                 return;\r
1411         }\r
1412 \r
1413         PROBE_STR("ConnectionReceive");\r
1414 \r
1415         s = c->Session;\r
1416 \r
1417         if (s->Hub != NULL)\r
1418         {\r
1419                 no_spinlock_for_delay = s->Hub->Option->NoSpinLockForPacketDelay;\r
1420         }\r
1421 \r
1422         now = Tick64();\r
1423 \r
1424         if (c->RecvBuf == NULL)\r
1425         {\r
1426                 c->RecvBuf = Malloc(RECV_BUF_SIZE);\r
1427         }\r
1428         buf = c->RecvBuf;\r
1429 \r
1430         // プロトコル\r
1431         if (c->Protocol == CONNECTION_TCP)\r
1432         {\r
1433                 // TCP\r
1434                 TCP *tcp = c->Tcp;\r
1435 \r
1436                 // コネクション切断間隔が指定されている場合はコネクションの切断を行う\r
1437                 if (s->ServerMode == false)\r
1438                 {\r
1439                         if (s->ClientOption->ConnectionDisconnectSpan != 0)\r
1440                         {\r
1441                                 LockList(tcp->TcpSockList);\r
1442                                 {\r
1443                                         UINT i;\r
1444                                         for (i = 0;i < LIST_NUM(tcp->TcpSockList);i++)\r
1445                                         {\r
1446                                                 TCPSOCK *ts = LIST_DATA(tcp->TcpSockList, i);\r
1447                                                 if (ts->DisconnectTick != 0 &&\r
1448                                                         ts->DisconnectTick <= now)\r
1449                                                 {\r
1450                                                         Debug("ts->DisconnectTick <= now\n");\r
1451                                                         Disconnect(ts->Sock);\r
1452                                                 }\r
1453                                         }\r
1454                                 }\r
1455                                 UnlockList(tcp->TcpSockList);\r
1456                         }\r
1457                 }\r
1458 \r
1459                 if (s->HalfConnection && (s->ServerMode == false))\r
1460                 {\r
1461                         // 現在の TCP コネクションの方向を調べ、\r
1462                         // 一方向しか無く かつコネクション数が限界の場合は\r
1463                         // 1 つ切断する\r
1464                         LockList(tcp->TcpSockList);\r
1465                         {\r
1466                                 UINT i, num;\r
1467                                 UINT c2s, s2c;\r
1468                                 c2s = s2c = 0;\r
1469                                 num = LIST_NUM(tcp->TcpSockList);\r
1470                                 if (num >= s->MaxConnection)\r
1471                                 {\r
1472                                         TCPSOCK *ts;\r
1473                                         for (i = 0;i < num;i++)\r
1474                                         {\r
1475                                                 ts = LIST_DATA(tcp->TcpSockList, i);\r
1476                                                 if (ts->Direction == TCP_SERVER_TO_CLIENT)\r
1477                                                 {\r
1478                                                         s2c++;\r
1479                                                 }\r
1480                                                 else\r
1481                                                 {\r
1482                                                         c2s++;\r
1483                                                 }\r
1484                                         }\r
1485                                         if (s2c == 0 || c2s == 0)\r
1486                                         {\r
1487                                                 // 最後のソケットを切断する\r
1488                                                 Disconnect(ts->Sock);\r
1489                                                 Debug("Disconnect (s2c=%u, c2s=%u)\n", s2c, c2s);\r
1490                                         }\r
1491                                 }\r
1492                         }\r
1493                         UnlockList(tcp->TcpSockList);\r
1494                 }\r
1495 \r
1496                 // ソケットセットの初期化\r
1497                 InitSockSet(&set);\r
1498                 LockList(tcp->TcpSockList);\r
1499                 {\r
1500                         num = LIST_NUM(tcp->TcpSockList);\r
1501                         tcpsocks = ToArrayEx(tcp->TcpSockList, true);\r
1502                 }\r
1503                 UnlockList(tcp->TcpSockList);\r
1504 \r
1505                 for (i = 0;i < num;i++)\r
1506                 {\r
1507                         AddSockSet(&set, tcpsocks[i]->Sock);\r
1508                 }\r
1509 \r
1510                 // Select\r
1511                 time = SELECT_TIME;\r
1512                 if (s->VirtualHost)\r
1513                 {\r
1514                         time = MIN(time, SELECT_TIME_FOR_NAT);\r
1515                 }\r
1516                 time = MIN(time, GetNextDelayedPacketTickDiff(s));\r
1517                 num_delayed = LIST_NUM(s->DelayedPacketList);\r
1518 \r
1519                 PROBE_STR("ConnectionReceive: Select 0");\r
1520 \r
1521                 if (s->Flag1 != set.NumSocket)\r
1522                 {\r
1523                         Select(&set, (num_delayed == 0 ? time : 1), c1, c2);\r
1524                         s->Flag1 = set.NumSocket;\r
1525                 }\r
1526                 else\r
1527                 {\r
1528                         if (no_spinlock_for_delay || time >= 50 || num_delayed == false)\r
1529                         {\r
1530                                 Select(&set, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);\r
1531                                 s->Flag1 = set.NumSocket;\r
1532                         }\r
1533                         else\r
1534                         {\r
1535                                 YieldCpu();\r
1536                         }\r
1537                 }\r
1538 \r
1539                 PROBE_STR("ConnectionReceive: Select 1");\r
1540 \r
1541                 // TCP ソケットに到着しているデータをすべて読み込む\r
1542                 for (i = 0;i < num;i++)\r
1543                 {\r
1544                         TCPSOCK *ts = tcpsocks[i];\r
1545                         if (ts->WantSize == 0)\r
1546                         {\r
1547                                 // 最初に必ず sizeof(UINT) だけ読み込む\r
1548                                 ts->WantSize = sizeof(UINT);\r
1549                         }\r
1550 \r
1551 RECV_START:\r
1552                         // 受信\r
1553                         size = TcpSockRecv(s, ts, buf, RECV_BUF_SIZE);\r
1554                         if (size == 0)\r
1555                         {\r
1556 DISCONNECT_THIS_TCP:\r
1557                                 s->LastTryAddConnectTime = Tick64();\r
1558                                 // 通信が切断された\r
1559                                 LockList(tcp->TcpSockList);\r
1560                                 {\r
1561                                         // ソケットリストからこのソケットを削除する\r
1562                                         Delete(tcp->TcpSockList, ts);\r
1563                                         // TCPSOCK の解放\r
1564                                         FreeTcpSock(ts);\r
1565                                         // デクリメント\r
1566                                         Dec(c->CurrentNumConnection);\r
1567                                         Debug("--- TCP Connection Decremented: %u (%s Line %u)\n", Count(c->CurrentNumConnection), __FILE__, __LINE__);\r
1568                                         Debug("LIST_NUM(tcp->TcpSockList): %u\n", LIST_NUM(tcp->TcpSockList));\r
1569                                 }\r
1570                                 UnlockList(tcp->TcpSockList);\r
1571 \r
1572                                 continue;\r
1573                         }\r
1574                         else if (size == SOCK_LATER)\r
1575                         {\r
1576                                 // 受信待ち状態: 何もしない\r
1577                                 if (IS_RECV_TCP_SOCK(ts))\r
1578                                 {\r
1579                                         if ((now > ts->LastCommTime) && ((now - ts->LastCommTime) >= ((UINT64)s->Timeout)))\r
1580                                         {\r
1581                                                 // このコネクションはタイムアウトした\r
1582                                                 Debug("Connection %u Timeouted.\n", i);\r
1583                                                 goto DISCONNECT_THIS_TCP;\r
1584                                         }\r
1585                                 }\r
1586                         }\r
1587                         else\r
1588                         {\r
1589                                 // 最終通信時刻を更新\r
1590                                 ts->LastCommTime = now;\r
1591                                 c->Session->LastCommTime = now;\r
1592 \r
1593                                 // データが受信できたので FIFO に書き込む\r
1594                                 PROBE_DATA2("WriteRecvFifo", buf, size);\r
1595                                 WriteRecvFifo(s, ts, buf, size);\r
1596 \r
1597                                 // 受信バッファがいっぱいになったら受信をやめる\r
1598                                 if (ts->RecvFifo->size < MAX_SEND_SOCKET_QUEUE_SIZE)\r
1599                                 {\r
1600                                         goto RECV_START;\r
1601                                 }\r
1602                         }\r
1603 \r
1604                         // FIFO に書き込まれたデータを処理する\r
1605                         while (ts->RecvFifo->size >= ts->WantSize)\r
1606                         {\r
1607                                 UCHAR *buf;\r
1608                                 void *data;\r
1609                                 BLOCK *block;\r
1610                                 UINT sz;\r
1611                                 // すでに十分な量のデータが格納されている\r
1612                                 // データのポインタを取得\r
1613                                 buf = (UCHAR *)ts->RecvFifo->p + ts->RecvFifo->pos;\r
1614 \r
1615                                 switch (ts->Mode)\r
1616                                 {\r
1617                                 case 0:\r
1618                                         // データブロック個数\r
1619                                         ts->WantSize = sizeof(UINT);\r
1620                                         Copy(&sz, buf, sizeof(UINT));\r
1621                                         PROBE_DATA2("ReadFifo 0", buf, sizeof(UINT));\r
1622                                         sz = Endian32(sz);\r
1623                                         ts->NextBlockNum = sz;\r
1624                                         ReadFifo(ts->RecvFifo, NULL, sizeof(UINT));\r
1625 \r
1626                                         s->TotalRecvSize += sizeof(UINT);\r
1627                                         s->TotalRecvSizeReal += sizeof(UINT);\r
1628 \r
1629                                         ts->CurrentPacketNum = 0;\r
1630                                         if (ts->NextBlockNum != 0)\r
1631                                         {\r
1632                                                 if (ts->NextBlockNum == KEEP_ALIVE_MAGIC)\r
1633                                                 {\r
1634                                                         ts->Mode = 3;\r
1635                                                 }\r
1636                                                 else\r
1637                                                 {\r
1638                                                         ts->Mode = 1;\r
1639                                                 }\r
1640                                         }\r
1641                                         break;\r
1642 \r
1643                                 case 1:\r
1644                                         // データブロックサイズ\r
1645                                         Copy(&sz, buf, sizeof(UINT));\r
1646                                         sz = Endian32(sz);\r
1647                                         PROBE_DATA2("ReadFifo 1", buf, sizeof(UINT));\r
1648                                         if (sz > (MAX_PACKET_SIZE * 2))\r
1649                                         {\r
1650                                                 // おかしなデータサイズを受信した\r
1651                                                 // TCP/IP 通信エラー?\r
1652                                                 Debug("%s %u sz > (MAX_PACKET_SIZE * 2)\n", __FILE__, __LINE__);\r
1653                                                 Disconnect(ts->Sock);\r
1654                                         }\r
1655                                         ts->NextBlockSize = MIN(sz, MAX_PACKET_SIZE * 2);\r
1656                                         ReadFifo(ts->RecvFifo, NULL, sizeof(UINT));\r
1657 \r
1658                                         s->TotalRecvSize += sizeof(UINT);\r
1659                                         s->TotalRecvSizeReal += sizeof(UINT);\r
1660 \r
1661                                         ts->WantSize = ts->NextBlockSize;\r
1662                                         if (ts->WantSize != 0)\r
1663                                         {\r
1664                                                 ts->Mode = 2;\r
1665                                         }\r
1666                                         else\r
1667                                         {\r
1668                                                 ts->Mode = 1;\r
1669                                                 ts->WantSize = sizeof(UINT);\r
1670                                                 ts->CurrentPacketNum++;\r
1671                                                 if (ts->CurrentPacketNum >= ts->NextBlockNum)\r
1672                                                 {\r
1673                                                         ts->Mode = 0;\r
1674                                                 }\r
1675                                         }\r
1676                                         break;\r
1677 \r
1678                                 case 2:\r
1679                                         // データブロック本体\r
1680                                         ts->WantSize = sizeof(UINT);\r
1681                                         ts->CurrentPacketNum++;\r
1682                                         data = MallocFast(ts->NextBlockSize);\r
1683                                         Copy(data, buf, ts->NextBlockSize);\r
1684                                         PROBE_DATA2("ReadFifo 2", buf, ts->NextBlockSize);\r
1685                                         ReadFifo(ts->RecvFifo, NULL, ts->NextBlockSize);\r
1686                                         block = NewBlock(data, ts->NextBlockSize, s->UseCompress ? -1 : 0);\r
1687 \r
1688                                         if (block->Size > MAX_PACKET_SIZE)\r
1689                                         {\r
1690                                                 // パケットサイズ超過\r
1691                                                 FreeBlock(block);\r
1692                                         }\r
1693                                         else\r
1694                                         {\r
1695                                                 // データブロックをキューに追加\r
1696                                                 InsertReveicedBlockToQueue(c, block);\r
1697                                         }\r
1698 \r
1699                                         if (ts->CurrentPacketNum >= ts->NextBlockNum)\r
1700                                         {\r
1701                                                 // すべてのデータブロックの受信が完了\r
1702                                                 ts->Mode = 0;\r
1703                                         }\r
1704                                         else\r
1705                                         {\r
1706                                                 // 次のデータブロックサイズを受信\r
1707                                                 ts->Mode = 1;\r
1708                                         }\r
1709                                         break;\r
1710 \r
1711                                 case 3:\r
1712                                         // Keep-Alive パケットサイズ\r
1713                                         ts->Mode = 4;\r
1714                                         Copy(&sz, buf, sizeof(UINT));\r
1715                                         PROBE_DATA2("ReadFifo 3", buf, sizeof(UINT));\r
1716                                         sz = Endian32(sz);\r
1717                                         if (sz > MAX_KEEPALIVE_SIZE)\r
1718                                         {\r
1719                                                 // おかしなデータサイズを受信した\r
1720                                                 // TCP/IP 通信エラー?\r
1721                                                 Debug("%s %u sz > MAX_KEEPALIVE_SIZE\n", __FILE__, __LINE__);\r
1722                                                 Disconnect(ts->Sock);\r
1723                                         }\r
1724                                         ts->NextBlockSize = MIN(sz, MAX_KEEPALIVE_SIZE);\r
1725                                         ReadFifo(ts->RecvFifo, NULL, sizeof(UINT));\r
1726 \r
1727                                         s->TotalRecvSize += sizeof(UINT);\r
1728                                         s->TotalRecvSizeReal += sizeof(UINT);\r
1729 \r
1730                                         ts->WantSize = sz;\r
1731                                         break;\r
1732 \r
1733                                 case 4:\r
1734                                         // Keep-Alive パケット本体\r
1735                                         //Debug("KeepAlive Recved.\n");\r
1736                                         ts->Mode = 0;\r
1737                                         sz = ts->NextBlockSize;\r
1738                                         PROBE_DATA2("ReadFifo 4", NULL, 0);\r
1739                                         ReadFifo(ts->RecvFifo, NULL, sz);\r
1740 \r
1741                                         s->TotalRecvSize += sz;\r
1742                                         s->TotalRecvSizeReal += sz;\r
1743 \r
1744                                         ts->WantSize = sizeof(UINT);\r
1745                                         break;\r
1746                                 }\r
1747                         }\r
1748                 }\r
1749 \r
1750                 Free(tcpsocks);\r
1751         }\r
1752         else if (c->Protocol == CONNECTION_UDP)\r
1753         {\r
1754                 // UDP\r
1755                 UDP *udp = c->Udp;\r
1756                 SOCK *sock = NULL;\r
1757 \r
1758                 if (s->ServerMode == false)\r
1759                 {\r
1760                         Lock(c->lock);\r
1761                         {\r
1762                                 if (c->Udp->s != NULL)\r
1763                                 {\r
1764                                         sock = c->Udp->s;\r
1765                                         if (sock != NULL)\r
1766                                         {\r
1767                                                 AddRef(sock->ref);\r
1768                                         }\r
1769                                 }\r
1770                         }\r
1771                         Unlock(c->lock);\r
1772 \r
1773                         InitSockSet(&set);\r
1774 \r
1775                         if (sock != NULL)\r
1776                         {\r
1777                                 AddSockSet(&set, sock);\r
1778                         }\r
1779 \r
1780                         Select(&set, SELECT_TIME, c1, c2);\r
1781 \r
1782                         if (sock != NULL)\r
1783                         {\r
1784                                 IP ip;\r
1785                                 UINT port;\r
1786                                 UCHAR *buf;\r
1787                                 UINT size;\r
1788 \r
1789                                 while (true)\r
1790                                 {\r
1791                                         buf = c->RecvBuf;\r
1792                                         size = RecvFrom(sock, &ip, &port, buf, RECV_BUF_SIZE);\r
1793                                         if (size == 0 && sock->IgnoreRecvErr == false)\r
1794                                         {\r
1795                                                 Debug("UDP Socket Disconnected.\n");\r
1796                                                 Lock(c->lock);\r
1797                                                 {\r
1798                                                         ReleaseSock(udp->s);\r
1799                                                         udp->s = NULL;\r
1800                                                 }\r
1801                                                 Unlock(c->lock);\r
1802                                                 break;\r
1803                                         }\r
1804                                         else if (size == SOCK_LATER)\r
1805                                         {\r
1806                                                 break;\r
1807                                         }\r
1808                                         else\r
1809                                         {\r
1810                                                 if (size)\r
1811                                                 {\r
1812                                                         PutUDPPacketData(c, buf, size);\r
1813                                                 }\r
1814                                         }\r
1815                                 }\r
1816                         }\r
1817 \r
1818                         if (sock != NULL)\r
1819                         {\r
1820                                 Release(sock->ref);\r
1821                         }\r
1822                 }\r
1823                 else\r
1824                 {\r
1825                         Select(NULL, SELECT_TIME, c1, c2);\r
1826                 }\r
1827         }\r
1828         else if (c->Protocol == CONNECTION_HUB_SECURE_NAT)\r
1829         {\r
1830                 SNAT *snat = c->Session->SecureNAT;\r
1831                 VH *v = snat->Nat->Virtual;\r
1832                 UINT size;\r
1833                 void *data;\r
1834                 UINT num;\r
1835                 UINT select_wait_time = SELECT_TIME_FOR_NAT;\r
1836 \r
1837                 if (snat->Nat != NULL && snat->Nat->Option.UseNat == false)\r
1838                 {\r
1839                         select_wait_time = SELECT_TIME;\r
1840                 }\r
1841                 else\r
1842                 {\r
1843                         if (snat->Nat != NULL)\r
1844                         {\r
1845                                 LockList(v->NatTable);\r
1846                                 {\r
1847                                         if (LIST_NUM(v->NatTable) == 0 && LIST_NUM(v->ArpWaitTable) == 0)\r
1848                                         {\r
1849                                                 select_wait_time = SELECT_TIME;\r
1850                                         }\r
1851                                 }\r
1852                                 UnlockList(v->NatTable);\r
1853                         }\r
1854                 }\r
1855 \r
1856                 select_wait_time = MIN(select_wait_time, GetNextDelayedPacketTickDiff(s));\r
1857                 num_delayed = LIST_NUM(s->DelayedPacketList);\r
1858 \r
1859                 if (no_spinlock_for_delay || select_wait_time >= 50 || num_delayed == false)\r
1860                 {\r
1861                         Select(NULL, (num_delayed == 0 ? select_wait_time :\r
1862                                 (select_wait_time > 100 ? (select_wait_time - 100) : 1)), c1, c2);\r
1863                 }\r
1864                 else\r
1865                 {\r
1866                         YieldCpu();\r
1867                 }\r
1868 \r
1869                 num = 0;\r
1870 \r
1871                 // 仮想マシンからパケットを受信する\r
1872                 while (size = VirtualGetNextPacket(v, &data))\r
1873                 {\r
1874                         BLOCK *block;\r
1875 \r
1876                         // パケットブロックを生成\r
1877                         block = NewBlock(data, size, 0);\r
1878                         if (block->Size > MAX_PACKET_SIZE)\r
1879                         {\r
1880                                 // パケットサイズ超過\r
1881                                 FreeBlock(block);\r
1882                         }\r
1883                         else\r
1884                         {\r
1885                                 // データブロックをキューに追加\r
1886                                 InsertReveicedBlockToQueue(c, block);\r
1887                         }\r
1888                         num++;\r
1889                         if (num >= MAX_SEND_SOCKET_QUEUE_NUM)\r
1890                         {\r
1891 //                              WHERE;\r
1892                                 break;\r
1893                         }\r
1894                 }\r
1895         }\r
1896         else if (c->Protocol == CONNECTION_HUB_LINK_SERVER)\r
1897         {\r
1898                 // HUB リンク\r
1899                 // 単純に Cancel を待つだけ\r
1900                 if (c->SendBlocks->num_item == 0)\r
1901                 {\r
1902                         UINT time = SELECT_TIME;\r
1903 \r
1904                         time = MIN(time, GetNextDelayedPacketTickDiff(s));\r
1905                         num_delayed = LIST_NUM(s->DelayedPacketList);\r
1906 \r
1907                         if (no_spinlock_for_delay || time >= 50 || num_delayed == false)\r
1908                         {\r
1909                                 Select(NULL, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);\r
1910                         }\r
1911                         else\r
1912                         {\r
1913                                 YieldCpu();\r
1914                         }\r
1915                 }\r
1916         }\r
1917         else if (c->Protocol == CONNECTION_HUB_LAYER3)\r
1918         {\r
1919                 // Layer-3 スイッチ セッション\r
1920                 L3IF *f = s->L3If;\r
1921                 UINT size, num = 0;\r
1922                 void *data;\r
1923 \r
1924                 if (f->SendQueue->num_item == 0)\r
1925                 {\r
1926                         UINT time = SELECT_TIME_FOR_NAT;\r
1927 \r
1928                         if (f->ArpWaitTable != NULL)\r
1929                         {\r
1930                                 LockList(f->ArpWaitTable);\r
1931                                 {\r
1932                                         if (LIST_NUM(f->ArpWaitTable) == 0)\r
1933                                         {\r
1934                                                 time = SELECT_TIME;\r
1935                                         }\r
1936                                 }\r
1937                                 UnlockList(f->ArpWaitTable);\r
1938                         }\r
1939 \r
1940                         time = MIN(time, GetNextDelayedPacketTickDiff(s));\r
1941                         num_delayed = LIST_NUM(s->DelayedPacketList);\r
1942 \r
1943                         if (no_spinlock_for_delay || time >= 50 || num_delayed == false)\r
1944                         {\r
1945                                 Select(NULL, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);\r
1946                         }\r
1947                         else\r
1948                         {\r
1949                                 YieldCpu();\r
1950                         }\r
1951                 }\r
1952 \r
1953                 // 次のパケットを取得する\r
1954                 while (size = L3GetNextPacket(f, &data))\r
1955                 {\r
1956                         BLOCK *block = NewBlock(data, size, 0);\r
1957                         if (block->Size > MAX_PACKET_SIZE)\r
1958                         {\r
1959                                 FreeBlock(block);\r
1960                         }\r
1961                         else\r
1962                         {\r
1963                                 InsertReveicedBlockToQueue(c, block);\r
1964                         }\r
1965 \r
1966                         num++;\r
1967                         if (num >= MAX_SEND_SOCKET_QUEUE_NUM)\r
1968                         {\r
1969                                 break;\r
1970                         }\r
1971                 }\r
1972         }\r
1973         else if (c->Protocol == CONNECTION_HUB_BRIDGE)\r
1974         {\r
1975                 BRIDGE *b = c->Session->Bridge;\r
1976 \r
1977                 // Bridge セッション\r
1978                 if (b->Active)\r
1979                 {\r
1980                         void *data;\r
1981                         UINT ret;\r
1982                         UINT num = 0;\r
1983                         bool check_device_num = false;\r
1984                         UINT time = SELECT_TIME;\r
1985 \r
1986                         time = MIN(time, GetNextDelayedPacketTickDiff(s));\r
1987                         num_delayed = LIST_NUM(s->DelayedPacketList);\r
1988 \r
1989                         // ブリッジ動作中\r
1990                         if (no_spinlock_for_delay || time >= 50 || num_delayed == false)\r
1991                         {\r
1992                                 Select(NULL, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);\r
1993                         }\r
1994                         else\r
1995                         {\r
1996                                 YieldCpu();\r
1997                         }\r
1998 \r
1999                         if ((b->LastNumDeviceCheck + BRIDGE_NUM_DEVICE_CHECK_SPAN) <= Tick64())\r
2000                         {\r
2001                                 check_device_num = true;\r
2002                                 b->LastNumDeviceCheck = Tick64();\r
2003                         }\r
2004 \r
2005                         // ブリッジから次のパケットを取得する\r
2006                         while (true)\r
2007                         {\r
2008                                 if (check_device_num && b->LastNumDevice != GetEthDeviceHash())\r
2009                                 {\r
2010                                         ret = INFINITE;\r
2011                                 }\r
2012                                 else\r
2013                                 {\r
2014                                         ret = EthGetPacket(b->Eth, &data);\r
2015                                 }\r
2016 \r
2017 #ifdef  OS_WIN32\r
2018                                 if (b->Eth != NULL && b->Eth->LoopbackBlock)\r
2019                                 {\r
2020                                         // ブリッジにおける eth デバイスがループバックパケットを遮断\r
2021                                         // する能力がある場合は CheckMac ポリシーを無効にする\r
2022                                         if (c->Session != NULL && c->Session->Policy != NULL)\r
2023                                         {\r
2024                                                 c->Session->Policy->CheckMac = false;\r
2025                                         }\r
2026                                 }\r
2027 #endif  // OS_WIN32\r
2028 \r
2029                                 if (ret == INFINITE)\r
2030                                 {\r
2031                                         // エラー発生 ブリッジを停止させる\r
2032                                         CloseEth(b->Eth);\r
2033                                         b->Eth = NULL;\r
2034                                         b->Active = false;\r
2035                                         ReleaseCancel(s->Cancel2);\r
2036                                         s->Cancel2 = NULL;\r
2037 \r
2038                                         HLog(s->Hub, "LH_BRIDGE_2", s->Name, b->Name);\r
2039                                         Debug("Bridge Device Error.\n");\r
2040 \r
2041                                         break;\r
2042                                 }\r
2043                                 else if (ret == 0)\r
2044                                 {\r
2045                                         // これ以上パケットが無い\r
2046                                         break;\r
2047                                 }\r
2048                                 else\r
2049                                 {\r
2050                                         // パケットをキューに追加\r
2051                                         BLOCK *block = NewBlock(data, ret, 0);\r
2052 \r
2053                                         PROBE_DATA2("ConnectionReceive: NewBlock", data, ret);\r
2054 \r
2055                                         if (ret > 1514)\r
2056                                         {\r
2057                                                 NormalizeEthMtu(b, c, ret);\r
2058                                         }\r
2059 \r
2060                                         if (block->Size > MAX_PACKET_SIZE)\r
2061                                         {\r
2062                                                 // パケットサイズ超過\r
2063                                                 FreeBlock(block);\r
2064                                         }\r
2065                                         else\r
2066                                         {\r
2067                                                 InsertReveicedBlockToQueue(c, block);\r
2068                                         }\r
2069                                         num++;\r
2070                                         if (num >= MAX_SEND_SOCKET_QUEUE_NUM)\r
2071                                         {\r
2072 //                                              WHERE;\r
2073                                                 break;\r
2074                                         }\r
2075                                 }\r
2076                         }\r
2077                 }\r
2078                 else\r
2079                 {\r
2080                         ETH *e;\r
2081                         // 現在ブリッジは停止している\r
2082                         Select(NULL, SELECT_TIME, c1, NULL);\r
2083 \r
2084                         if (b->LastBridgeTry == 0 || (b->LastBridgeTry + BRIDGE_TRY_SPAN) <= Tick64())\r
2085                         {\r
2086                                 b->LastBridgeTry = Tick64();\r
2087 \r
2088                                 // Ethernet デバイスを開こうとしてみる\r
2089                                 e = OpenEth(b->Name, b->Local, b->TapMode, b->TapMacAddress);\r
2090                                 if (e != NULL)\r
2091                                 {\r
2092                                         // 成功\r
2093                                         b->Eth = e;\r
2094                                         b->Active = true;\r
2095                                         b->LastNumDeviceCheck = Tick64();\r
2096                                         b->LastNumDevice = GetEthDeviceHash();\r
2097 \r
2098                                         Debug("Bridge Open Succeed.\n");\r
2099 \r
2100                                         HLog(c->Session->Hub, "LH_BRIDGE_1", c->Session->Name, b->Name);\r
2101 \r
2102                                         s->Cancel2 = EthGetCancel(b->Eth);\r
2103                                 }\r
2104                         }\r
2105                 }\r
2106         }\r
2107 }\r
2108 \r
2109 // Ethernet デバイスの MTU を正規化する\r
2110 void NormalizeEthMtu(BRIDGE *b, CONNECTION *c, UINT packet_size)\r
2111 {\r
2112         // 引数チェック\r
2113         if (packet_size == 0 || b == NULL || c == NULL)\r
2114         {\r
2115                 return;\r
2116         }\r
2117 \r
2118         // 現在の MTU を超えるパケットの場合は MTU を引き上げる\r
2119         if (EthIsChangeMtuSupported(b->Eth))\r
2120         {\r
2121                 UINT currentMtu = EthGetMtu(b->Eth);\r
2122                 if (currentMtu != 0)\r
2123                 {\r
2124                         if (packet_size > currentMtu)\r
2125                         {\r
2126                                 bool ok = EthSetMtu(b->Eth, packet_size);\r
2127 \r
2128                                 if (ok)\r
2129                                 {\r
2130                                         HLog(c->Session->Hub, "LH_SET_MTU", c->Session->Name,\r
2131                                                 b->Name, currentMtu, packet_size, packet_size);\r
2132                                 }\r
2133                                 else\r
2134                                 {\r
2135                                         UINT64 now = Tick64();\r
2136 \r
2137                                         if (b->LastChangeMtuError == 0 ||\r
2138                                                 now >= (b->LastChangeMtuError + 60000ULL))\r
2139                                         {\r
2140                                                 HLog(c->Session->Hub, "LH_SET_MTU_ERROR", c->Session->Name,\r
2141                                                         b->Name, currentMtu, packet_size, packet_size);\r
2142 \r
2143                                                 b->LastChangeMtuError = now;\r
2144                                         }\r
2145                                 }\r
2146                         }\r
2147                 }\r
2148         }\r
2149 }\r
2150 \r
2151 // ブロックの解放\r
2152 void FreeBlock(BLOCK *b)\r
2153 {\r
2154         // 引数チェック\r
2155         if (b == NULL)\r
2156         {\r
2157                 return;\r
2158         }\r
2159 \r
2160         Free(b->Buf);\r
2161         Free(b);\r
2162 }\r
2163 \r
2164 // 新しいブロック作成\r
2165 BLOCK *NewBlock(void *data, UINT size, int compress)\r
2166 {\r
2167         BLOCK *b;\r
2168         // 引数チェック\r
2169         if (data == NULL)\r
2170         {\r
2171                 return NULL;\r
2172         }\r
2173 \r
2174         b = ZeroMallocFast(sizeof(BLOCK));\r
2175 \r
2176         if (compress == 0)\r
2177         {\r
2178                 // 非圧縮\r
2179                 b->Compressed = FALSE;\r
2180                 b->Buf = data;\r
2181                 b->Size = size;\r
2182                 b->SizeofData = size;\r
2183         }\r
2184         else if (compress == 1)\r
2185         {\r
2186                 UINT max_size;\r
2187 \r
2188                 // 圧縮\r
2189                 b->Compressed = TRUE;\r
2190                 max_size = CalcCompress(size);\r
2191                 b->Buf = MallocFast(max_size);\r
2192                 b->Size = Compress(b->Buf, max_size, data, size);\r
2193                 b->SizeofData = size;\r
2194 \r
2195                 // 古いデータブロックを破棄\r
2196                 Free(data);\r
2197         }\r
2198         else\r
2199         {\r
2200                 // 展開\r
2201                 UINT max_size;\r
2202 \r
2203                 max_size = MAX_PACKET_SIZE;\r
2204                 b->Buf = MallocFast(max_size);\r
2205                 b->Size = Uncompress(b->Buf, max_size, data, size);\r
2206                 b->SizeofData = size;\r
2207 \r
2208                 // 古いデータを破棄\r
2209                 Free(data);\r
2210         }\r
2211 \r
2212         return b;\r
2213 }\r
2214 \r
2215 // TCP ソケットの作成\r
2216 TCPSOCK *NewTcpSock(SOCK *s)\r
2217 {\r
2218         TCPSOCK *ts;\r
2219         // 引数チェック\r
2220         if (s == NULL)\r
2221         {\r
2222                 return NULL;\r
2223         }\r
2224 \r
2225         ts = ZeroMalloc(sizeof(TCPSOCK));\r
2226 \r
2227         ts->Sock = s;\r
2228         AddRef(s->ref);\r
2229 \r
2230         ts->RecvFifo = NewFifo();\r
2231         ts->SendFifo = NewFifo();\r
2232         ts->LastCommTime = Tick64();\r
2233 \r
2234         // タイムアウト値の解消\r
2235         SetTimeout(s, TIMEOUT_INFINITE);\r
2236 \r
2237         return ts;\r
2238 }\r
2239 \r
2240 // TCP ソケット用暗号化鍵の設定\r
2241 void InitTcpSockRc4Key(TCPSOCK *ts, bool server_mode)\r
2242 {\r
2243         RC4_KEY_PAIR *pair;\r
2244         CRYPT *c1, *c2;\r
2245         // 引数チェック\r
2246         if (ts == NULL)\r
2247         {\r
2248                 return;\r
2249         }\r
2250 \r
2251         pair = &ts->Rc4KeyPair;\r
2252 \r
2253         c1 = NewCrypt(pair->ClientToServerKey, sizeof(pair->ClientToServerKey));\r
2254         c2 = NewCrypt(pair->ServerToClientKey, sizeof(pair->ServerToClientKey));\r
2255 \r
2256         if (server_mode)\r
2257         {\r
2258                 ts->RecvKey = c1;\r
2259                 ts->SendKey = c2;\r
2260         }\r
2261         else\r
2262         {\r
2263                 ts->SendKey = c1;\r
2264                 ts->RecvKey = c2;\r
2265         }\r
2266 }\r
2267 \r
2268 // TCP ソケットの解放\r
2269 void FreeTcpSock(TCPSOCK *ts)\r
2270 {\r
2271         // 引数チェック\r
2272         if (ts == NULL)\r
2273         {\r
2274                 return;\r
2275         }\r
2276 \r
2277         Disconnect(ts->Sock);\r
2278         ReleaseSock(ts->Sock);\r
2279         ReleaseFifo(ts->RecvFifo);\r
2280         ReleaseFifo(ts->SendFifo);\r
2281 \r
2282         if (ts->SendKey)\r
2283         {\r
2284                 FreeCrypt(ts->SendKey);\r
2285         }\r
2286         if (ts->RecvKey)\r
2287         {\r
2288                 FreeCrypt(ts->RecvKey);\r
2289         }\r
2290 \r
2291         Free(ts);\r
2292 }\r
2293 \r
2294 // コネクションのトンネリングモードを終了する\r
2295 void EndTunnelingMode(CONNECTION *c)\r
2296 {\r
2297         // 引数チェック\r
2298         if (c == NULL)\r
2299         {\r
2300                 return;\r
2301         }\r
2302 \r
2303         // プロトコル\r
2304         if (c->Protocol == CONNECTION_TCP)\r
2305         {\r
2306                 // TCP\r
2307                 DisconnectTcpSockets(c);\r
2308         }\r
2309         else\r
2310         {\r
2311                 // UDP\r
2312                 DisconnectUDPSockets(c);\r
2313         }\r
2314 }\r
2315 \r
2316 // コネクションをトンネリングモードに移行させる\r
2317 void StartTunnelingMode(CONNECTION *c)\r
2318 {\r
2319         SOCK *s;\r
2320         TCP *tcp;\r
2321         TCPSOCK *ts;\r
2322         IP ip;\r
2323         UINT port;\r
2324         // 引数チェック\r
2325         if (c == NULL)\r
2326         {\r
2327                 return;\r
2328         }\r
2329 \r
2330         tcp = c->Tcp;\r
2331 \r
2332         // プロトコル\r
2333         if (c->Protocol == CONNECTION_TCP)\r
2334         {\r
2335                 // TCP\r
2336                 s = c->FirstSock;\r
2337 \r
2338                 ts = NewTcpSock(s);\r
2339 \r
2340                 if (c->ServerMode == false)\r
2341                 {\r
2342                         if (c->Session->ClientOption->ConnectionDisconnectSpan != 0)\r
2343                         {\r
2344                                 ts->DisconnectTick = Tick64() + c->Session->ClientOption->ConnectionDisconnectSpan * (UINT64)1000;\r
2345                         }\r
2346                 }\r
2347 \r
2348                 LockList(tcp->TcpSockList);\r
2349                 {\r
2350                         Add(tcp->TcpSockList, ts);\r
2351                 }\r
2352                 UnlockList(tcp->TcpSockList);\r
2353                 ReleaseSock(s);\r
2354                 c->FirstSock = NULL;\r
2355         }\r
2356         else\r
2357         {\r
2358                 // UDP\r
2359                 s = c->FirstSock;\r
2360                 Copy(&ip, &s->RemoteIP, sizeof(IP));\r
2361                 // この時点で TCP コネクションは切断してよい\r
2362                 c->FirstSock = NULL;\r
2363                 Disconnect(s);\r
2364                 ReleaseSock(s);\r
2365 \r
2366                 // UDP 構造体の初期化\r
2367                 c->Udp = ZeroMalloc(sizeof(UDP));\r
2368 \r
2369                 if (c->ServerMode)\r
2370                 {\r
2371                         // サーバーモード\r
2372                         // エントリの追加\r
2373                         AddUDPEntry(c->Cedar, c->Session);\r
2374                         c->Udp->s = NULL;\r
2375                 }\r
2376                 else\r
2377                 {\r
2378                         port = c->Session->ClientOption->PortUDP;\r
2379                         // クライアントモード\r
2380                         c->Udp->s = NewUDP(0);\r
2381                         // IP アドレスとポート番号を書く\r
2382                         Copy(&c->Udp->ip, &ip, sizeof(IP));\r
2383                         c->Udp->port = port;\r
2384                 }\r
2385 \r
2386                 // キュー\r
2387                 c->Udp->BufferQueue = NewQueue();\r
2388         }\r
2389 }\r
2390 \r
2391 // 新しいコネクションを受け付ける関数\r
2392 void ConnectionAccept(CONNECTION *c)\r
2393 {\r
2394         SOCK *s;\r
2395         X *x;\r
2396         K *k;\r
2397         char tmp[128];\r
2398         // 引数チェック\r
2399         if (c == NULL)\r
2400         {\r
2401                 return;\r
2402         }\r
2403 \r
2404         Debug("ConnectionAccept()\n");\r
2405 \r
2406         // ソケットを取得する\r
2407         s = c->FirstSock;\r
2408         AddRef(s->ref);\r
2409 \r
2410         Dec(c->Cedar->AcceptingSockets);\r
2411 \r
2412         IPToStr(tmp, sizeof(tmp), &s->RemoteIP);\r
2413         SLog(c->Cedar, "LS_CONNECTION_START_1", tmp, s->RemoteHostname, s->RemotePort, c->Name);\r
2414 \r
2415         // タイムアウト設定\r
2416         SetTimeout(s, CONNECTING_TIMEOUT);\r
2417 \r
2418         // 暗号化アルゴリズムを指定する\r
2419         Lock(c->lock);\r
2420         {\r
2421                 if (c->Cedar->CipherList != NULL)\r
2422                 {\r
2423                         SetWantToUseCipher(s, c->Cedar->CipherList);\r
2424                 }\r
2425 \r
2426                 x = CloneX(c->Cedar->ServerX);\r
2427                 k = CloneK(c->Cedar->ServerK);\r
2428         }\r
2429         Unlock(c->lock);\r
2430 \r
2431         // SSL 通信を開始する\r
2432         Debug("StartSSL()\n");\r
2433         if (StartSSL(s, x, k) == false)\r
2434         {\r
2435                 // 失敗\r
2436                 Debug("Failed to StartSSL.\n");\r
2437                 FreeX(x);\r
2438                 FreeK(k);\r
2439                 goto ERROR;\r
2440         }\r
2441 \r
2442         FreeX(x);\r
2443         FreeK(k);\r
2444 \r
2445         SLog(c->Cedar, "LS_SSL_START", c->Name, s->CipherName);\r
2446 \r
2447         // 接続を受諾する\r
2448         if (ServerAccept(c) == false)\r
2449         {\r
2450                 // 失敗\r
2451                 Debug("ServerAccept Failed. Err = %u\n", c->Err);\r
2452                 goto ERROR;\r
2453         }\r
2454 \r
2455         if (c->flag1 == false)\r
2456         {\r
2457                 Debug("%s %u c->flag1 == false\n", __FILE__, __LINE__);\r
2458                 Disconnect(s);\r
2459         }\r
2460         DelConnection(c->Cedar, c);\r
2461         ReleaseSock(s);\r
2462         return;\r
2463 \r
2464 ERROR:\r
2465         Debug("ConnectionAccept() Error.\n");\r
2466         Disconnect(s);\r
2467         DelConnection(c->Cedar, c);\r
2468         ReleaseSock(s);\r
2469 }\r
2470 \r
2471 // 現在動作しているすべての追加コネクションを張るスレッドを中断する\r
2472 void StopAllAdditionalConnectThread(CONNECTION *c)\r
2473 {\r
2474         UINT i, num;\r
2475         SOCK **socks;\r
2476         THREAD **threads;\r
2477         // 引数チェック\r
2478         if (c == NULL || c->ServerMode != false)\r
2479         {\r
2480                 return;\r
2481         }\r
2482 \r
2483         // まずソケットを切断する\r
2484         LockList(c->ConnectingSocks);\r
2485         {\r
2486                 num = LIST_NUM(c->ConnectingSocks);\r
2487                 socks = ToArray(c->ConnectingSocks);\r
2488                 DeleteAll(c->ConnectingSocks);\r
2489         }\r
2490         UnlockList(c->ConnectingSocks);\r
2491         for (i = 0;i < num;i++)\r
2492         {\r
2493                 Disconnect(socks[i]);\r
2494                 ReleaseSock(socks[i]);\r
2495         }\r
2496         Free(socks);\r
2497 \r
2498         // 次にスレッドの停止を待つ\r
2499         LockList(c->ConnectingThreads);\r
2500         {\r
2501                 num = LIST_NUM(c->ConnectingThreads);\r
2502                 Debug("c->ConnectingThreads: %u\n", num);\r
2503                 threads = ToArray(c->ConnectingThreads);\r
2504                 DeleteAll(c->ConnectingThreads);\r
2505         }\r
2506         UnlockList(c->ConnectingThreads);\r
2507         for (i = 0;i < num;i++)\r
2508         {\r
2509                 WaitThread(threads[i], INFINITE);\r
2510                 ReleaseThread(threads[i]);\r
2511         }\r
2512         Free(threads);\r
2513 }\r
2514 \r
2515 // コネクションの停止\r
2516 void StopConnection(CONNECTION *c, bool no_wait)\r
2517 {\r
2518         // 引数チェック\r
2519         if (c == NULL)\r
2520         {\r
2521                 return;\r
2522         }\r
2523 \r
2524         Debug("Stop Connection: %s\n", c->Name);\r
2525 \r
2526         // 停止フラグ\r
2527         c->Halt = true;\r
2528         Disconnect(c->FirstSock);\r
2529 \r
2530         if (no_wait == false)\r
2531         {\r
2532                 // スレッド停止まで待機\r
2533                 WaitThread(c->Thread, INFINITE);\r
2534         }\r
2535 }\r
2536 \r
2537 // UDP ソケットをすべて閉じる\r
2538 void DisconnectUDPSockets(CONNECTION *c)\r
2539 {\r
2540         // 引数チェック\r
2541         if (c == NULL)\r
2542         {\r
2543                 return;\r
2544         }\r
2545         if (c->Protocol != CONNECTION_UDP)\r
2546         {\r
2547                 return;\r
2548         }\r
2549 \r
2550         // エントリの削除\r
2551         if (c->ServerMode)\r
2552         {\r
2553                 DelUDPEntry(c->Cedar, c->Session);\r
2554         }\r
2555 \r
2556         // UDP 構造体の削除\r
2557         if (c->Udp != NULL)\r
2558         {\r
2559                 if (c->Udp->s != NULL)\r
2560                 {\r
2561                         ReleaseSock(c->Udp->s);\r
2562                 }\r
2563                 if (c->Udp->BufferQueue != NULL)\r
2564                 {\r
2565                         // キューの解放\r
2566                         BUF *b;\r
2567                         while (b = GetNext(c->Udp->BufferQueue))\r
2568                         {\r
2569                                 FreeBuf(b);\r
2570                         }\r
2571                         ReleaseQueue(c->Udp->BufferQueue);\r
2572                 }\r
2573                 Free(c->Udp);\r
2574                 c->Udp = NULL;\r
2575         }\r
2576 \r
2577         if (c->FirstSock != NULL)\r
2578         {\r
2579                 Disconnect(c->FirstSock);\r
2580                 ReleaseSock(c->FirstSock);\r
2581                 c->FirstSock = NULL;\r
2582         }\r
2583 }\r
2584 \r
2585 // TCP コネクションをすべて閉じる\r
2586 void DisconnectTcpSockets(CONNECTION *c)\r
2587 {\r
2588         UINT i, num;\r
2589         TCP *tcp;\r
2590         TCPSOCK **tcpsocks;\r
2591         // 引数チェック\r
2592         if (c == NULL)\r
2593         {\r
2594                 return;\r
2595         }\r
2596         if (c->Protocol != CONNECTION_TCP)\r
2597         {\r
2598                 return;\r
2599         }\r
2600 \r
2601         tcp = c->Tcp;\r
2602         LockList(tcp->TcpSockList);\r
2603         {\r
2604                 tcpsocks = ToArray(tcp->TcpSockList);\r
2605                 num = LIST_NUM(tcp->TcpSockList);\r
2606                 DeleteAll(tcp->TcpSockList);\r
2607         }\r
2608         UnlockList(tcp->TcpSockList);\r
2609 \r
2610         if (num != 0)\r
2611         {\r
2612                 Debug("--- SOCKET STATUS ---\n");\r
2613                 for (i = 0;i < num;i++)\r
2614                 {\r
2615                         TCPSOCK *ts = tcpsocks[i];\r
2616                         Debug(" SOCK %2u: %u\n", i, ts->Sock->SendSize);\r
2617                         FreeTcpSock(ts);\r
2618                 }\r
2619         }\r
2620 \r
2621         Free(tcpsocks);\r
2622 }\r
2623 \r
2624 // コネクションのクリーンアップ\r
2625 void CleanupConnection(CONNECTION *c)\r
2626 {\r
2627         UINT i, num;\r
2628         // 引数チェック\r
2629         if (c == NULL)\r
2630         {\r
2631                 return;\r
2632         }\r
2633 \r
2634         DeleteLock(c->lock);\r
2635         ReleaseCedar(c->Cedar);\r
2636 \r
2637         switch (c->Protocol)\r
2638         {\r
2639         case CONNECTION_TCP:\r
2640                 // TCP コネクションリストの解放\r
2641                 DisconnectTcpSockets(c);\r
2642                 break;\r
2643 \r
2644         case CONNECTION_UDP:\r
2645                 break;\r
2646         }\r
2647 \r
2648         ReleaseList(c->Tcp->TcpSockList);\r
2649         Free(c->Tcp);\r
2650 \r
2651         ReleaseSock(c->FirstSock);\r
2652         c->FirstSock = NULL;\r
2653 \r
2654         ReleaseThread(c->Thread);\r
2655         Free(c->Name);\r
2656 \r
2657         // すべての送信ブロックと受信ブロックを解放\r
2658         if (c->SendBlocks)\r
2659         {\r
2660                 LockQueue(c->SendBlocks);\r
2661                 {\r
2662                         BLOCK *b;\r
2663                         while (b = GetNext(c->SendBlocks))\r
2664                         {\r
2665                                 FreeBlock(b);\r
2666                         }\r
2667                 }\r
2668                 UnlockQueue(c->SendBlocks);\r
2669         }\r
2670         if (c->SendBlocks2)\r
2671         {\r
2672                 LockQueue(c->SendBlocks2);\r
2673                 {\r
2674                         BLOCK *b;\r
2675                         while (b = GetNext(c->SendBlocks2))\r
2676                         {\r
2677                                 FreeBlock(b);\r
2678                         }\r
2679                 }\r
2680                 UnlockQueue(c->SendBlocks2);\r
2681         }\r
2682         if (c->ReceivedBlocks)\r
2683         {\r
2684                 LockQueue(c->ReceivedBlocks);\r
2685                 {\r
2686                         BLOCK *b;\r
2687                         while (b = GetNext(c->ReceivedBlocks))\r
2688                         {\r
2689                                 FreeBlock(b);\r
2690                         }\r
2691                 }\r
2692                 UnlockQueue(c->ReceivedBlocks);\r
2693         }\r
2694 \r
2695         if (c->ConnectingThreads)\r
2696         {\r
2697                 THREAD **threads;\r
2698                 LockList(c->ConnectingThreads);\r
2699                 {\r
2700                         num = LIST_NUM(c->ConnectingThreads);\r
2701                         threads = ToArray(c->ConnectingThreads);\r
2702                         for (i = 0;i < num;i++)\r
2703                         {\r
2704                                 ReleaseThread(threads[i]);\r
2705                         }\r
2706                         Free(threads);\r
2707                 }\r
2708                 UnlockList(c->ConnectingThreads);\r
2709                 ReleaseList(c->ConnectingThreads);\r
2710         }\r
2711 \r
2712         if (c->ConnectingSocks)\r
2713         {\r
2714                 SOCK **socks;\r
2715                 LockList(c->ConnectingSocks);\r
2716                 {\r
2717                         num = LIST_NUM(c->ConnectingSocks);\r
2718                         socks = ToArray(c->ConnectingSocks);\r
2719                         for (i = 0;i < num;i++)\r
2720                         {\r
2721                                 Disconnect(socks[i]);\r
2722                                 ReleaseSock(socks[i]);\r
2723                         }\r
2724                         Free(socks);\r
2725                 }\r
2726                 UnlockList(c->ConnectingSocks);\r
2727                 ReleaseList(c->ConnectingSocks);\r
2728         }\r
2729 \r
2730         if (c->RecvBuf)\r
2731         {\r
2732                 Free(c->RecvBuf);\r
2733         }\r
2734 \r
2735         if (c->ServerX != NULL)\r
2736         {\r
2737                 FreeX(c->ServerX);\r
2738         }\r
2739 \r
2740         if (c->ClientX != NULL)\r
2741         {\r
2742                 FreeX(c->ClientX);\r
2743         }\r
2744 \r
2745         ReleaseQueue(c->ReceivedBlocks);\r
2746         ReleaseQueue(c->SendBlocks);\r
2747         ReleaseQueue(c->SendBlocks2);\r
2748 \r
2749         DeleteCounter(c->CurrentNumConnection);\r
2750 \r
2751         if (c->CipherName != NULL)\r
2752         {\r
2753                 Free(c->CipherName);\r
2754         }\r
2755 \r
2756         Free(c);\r
2757 }\r
2758 \r
2759 // コネクションの解放\r
2760 void ReleaseConnection(CONNECTION *c)\r
2761 {\r
2762         // 引数チェック\r
2763         if (c == NULL)\r
2764         {\r
2765                 return;\r
2766         }\r
2767 \r
2768         if (Release(c->ref) == 0)\r
2769         {\r
2770                 CleanupConnection(c);\r
2771         }\r
2772 }\r
2773 \r
2774 // コネクションの比較\r
2775 int CompareConnection(void *p1, void *p2)\r
2776 {\r
2777         CONNECTION *c1, *c2;\r
2778         if (p1 == NULL || p2 == NULL)\r
2779         {\r
2780                 return 0;\r
2781         }\r
2782         c1 = *(CONNECTION **)p1;\r
2783         c2 = *(CONNECTION **)p2;\r
2784         if (c1 == NULL || c2 == NULL)\r
2785         {\r
2786                 return 0;\r
2787         }\r
2788 \r
2789         return StrCmpi(c1->Name, c2->Name);\r
2790 }\r
2791 \r
2792 // サーバーコネクションの作成\r
2793 CONNECTION *NewServerConnection(CEDAR *cedar, SOCK *s, THREAD *t)\r
2794 {\r
2795         CONNECTION *c;\r
2796         // 引数チェック\r
2797         if (cedar == NULL)\r
2798         {\r
2799                 return NULL;\r
2800         }\r
2801 \r
2802         c = ZeroMalloc(sizeof(CONNECTION));\r
2803         c->ConnectedTick = Tick64();\r
2804         c->lock = NewLock();\r
2805         c->ref = NewRef();\r
2806         c->Cedar = cedar;\r
2807         AddRef(c->Cedar->ref);\r
2808         c->Protocol = CONNECTION_TCP;\r
2809         c->Type = CONNECTION_TYPE_INIT;\r
2810         c->FirstSock = s;\r
2811         if (s != NULL)\r
2812         {\r
2813                 AddRef(c->FirstSock->ref);\r
2814                 Copy(&c->ClientIp, &s->RemoteIP, sizeof(IP));\r
2815                 StrCpy(c->ClientHostname, sizeof(c->ClientHostname), s->RemoteHostname);\r
2816         }\r
2817         c->Tcp = ZeroMalloc(sizeof(TCP));\r
2818         c->Tcp->TcpSockList = NewList(NULL);\r
2819         c->ServerMode = true;\r
2820         c->Status = CONNECTION_STATUS_ACCEPTED;\r
2821         c->Name = CopyStr("INITING");\r
2822         c->Thread = t;\r
2823         AddRef(t->ref);\r
2824         c->CurrentNumConnection = NewCounter();\r
2825         Inc(c->CurrentNumConnection);\r
2826 \r
2827         c->ServerVer = cedar->Version;\r
2828         c->ServerBuild = cedar->Build;\r
2829         StrCpy(c->ServerStr, sizeof(c->ServerStr), cedar->ServerStr);\r
2830         GetServerProductName(cedar->Server, c->ServerStr, sizeof(c->ServerStr));\r
2831 \r
2832         if (s != NULL && s->RemoteX != NULL)\r
2833         {\r
2834                 c->ServerX = CloneX(s->RemoteX);\r
2835         }\r
2836 \r
2837         // キューの作成\r
2838         c->ReceivedBlocks = NewQueue();\r
2839         c->SendBlocks = NewQueue();\r
2840         c->SendBlocks2 = NewQueue();\r
2841 \r
2842         return c;\r
2843 }\r
2844 \r
2845 // クライアントコネクションの作成\r
2846 CONNECTION *NewClientConnection(SESSION *s)\r
2847 {\r
2848         return NewClientConnectionEx(s, NULL, 0, 0);\r
2849 }\r
2850 CONNECTION *NewClientConnectionEx(SESSION *s, char *client_str, UINT client_ver, UINT client_build)\r
2851 {\r
2852         CONNECTION *c;\r
2853 \r
2854         // CONNECTION オブジェクトの初期化\r
2855         c = ZeroMalloc(sizeof(CONNECTION));\r
2856         c->ConnectedTick = Tick64();\r
2857         c->lock = NewLock();\r
2858         c->ref = NewRef();\r
2859         c->Cedar = s->Cedar;\r
2860         AddRef(c->Cedar->ref);\r
2861         if (s->ClientOption->PortUDP == 0)\r
2862         {\r
2863                 // TCP\r
2864                 c->Protocol = CONNECTION_TCP;\r
2865                 c->Tcp = ZeroMalloc(sizeof(TCP));\r
2866                 c->Tcp->TcpSockList = NewList(NULL);\r
2867         }\r
2868         else\r
2869         {\r
2870                 // UDP\r
2871                 c->Protocol = CONNECTION_UDP;\r
2872         }\r
2873         c->ServerMode = false;\r
2874         c->Status = CONNECTION_STATUS_CONNECTING;\r
2875         c->Name = CopyStr("CLIENT_CONNECTION");\r
2876         c->Session = s;\r
2877         c->CurrentNumConnection = NewCounter();\r
2878         Inc(c->CurrentNumConnection);\r
2879 \r
2880         c->ConnectingThreads = NewList(NULL);\r
2881         c->ConnectingSocks = NewList(NULL);\r
2882 \r
2883         if (client_str == NULL)\r
2884         {\r
2885                 c->ClientVer = s->Cedar->Version;\r
2886                 c->ClientBuild = s->Cedar->Build;\r
2887 \r
2888                 if (c->Session->VirtualHost == false)\r
2889                 {\r
2890                         if (c->Session->LinkModeClient == false)\r
2891                         {\r
2892                                 StrCpy(c->ClientStr, sizeof(c->ClientStr), CEDAR_CLIENT_STR);\r
2893                         }\r
2894                         else\r
2895                         {\r
2896                                 StrCpy(c->ClientStr, sizeof(c->ClientStr), CEDAR_SERVER_LINK_STR);\r
2897                         }\r
2898                 }\r
2899                 else\r
2900                 {\r
2901                         StrCpy(c->ClientStr, sizeof(c->ClientStr), CEDAR_ROUTER_STR);\r
2902                 }\r
2903         }\r
2904         else\r
2905         {\r
2906                 c->ClientVer = client_ver;\r
2907                 c->ClientBuild = client_build;\r
2908                 StrCpy(c->ClientStr, sizeof(c->ClientStr), client_str);\r
2909         }\r
2910 \r
2911         // サーバー名とポート番号\r
2912         StrCpy(c->ServerName, sizeof(c->ServerName), s->ClientOption->Hostname);\r
2913         c->ServerPort = s->ClientOption->Port;\r
2914 \r
2915         // TLS 1.0 使用フラグ\r
2916         c->DontUseTls1 = s->ClientOption->NoTls1;\r
2917 \r
2918         // キューの作成\r
2919         c->ReceivedBlocks = NewQueue();\r
2920         c->SendBlocks = NewQueue();\r
2921         c->SendBlocks2 = NewQueue();\r
2922 \r
2923         return c;\r
2924 }\r
2925 \r
2926 \r