1 // SoftEther UT-VPN SourceCode
\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
8 // http://utvpn.tsukuba.ac.jp/
\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
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
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
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\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
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
81 #include "CedarPch.h"
\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
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
92 void InRpcSecureSign(SECURE_SIGN *t, PACK *p)
\r
95 if (t == NULL || p == NULL)
\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
109 void OutRpcSecureSign(PACK *p, SECURE_SIGN *t)
\r
112 if (p == NULL || t == NULL)
\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
125 void FreeRpcSecureSign(SECURE_SIGN *t)
\r
133 FreeX(t->ClientCert);
\r
137 BUF *NewKeepPacket(bool server_mode)
\r
140 char *string = KEEP_ALIVE_STRING;
\r
142 WriteBuf(b, string, StrLen(string));
\r
150 void KeepThread(THREAD *thread, void *param)
\r
152 KEEP *k = (KEEP *)param;
\r
154 char server_name[MAX_HOST_NAME_LEN + 1];
\r
159 if (thread == NULL || k == NULL)
\r
165 Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);
\r
175 if (StrLen(k->ServerName) != 0 && k->ServerPort != 0 && k->Interval != 0)
\r
177 StrCpy(server_name, sizeof(server_name), k->ServerName);
\r
178 server_port = k->ServerPort;
\r
179 udp_mode = k->UdpMode;
\r
193 Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);
\r
196 if (udp_mode == false)
\r
202 UINT64 connect_started_tick;
\r
203 bool changed = false;
\r
206 if (StrCmpi(k->ServerName, server_name) != 0 ||
\r
207 k->ServerPort != server_port || k->Enable == false ||
\r
217 goto WAIT_FOR_ENABLE;
\r
227 connect_started_tick = Tick64();
\r
228 s = ConnectEx2(server_name, server_port, KEEP_TCP_TIMEOUT, (bool *)&k->Halt);
\r
235 // 接続失敗 設定が変更されるかタイムアウトするまで待機する
\r
246 if (StrCmpi(k->ServerName, server_name) != 0 ||
\r
247 k->ServerPort != server_port || k->Enable == false ||
\r
258 goto WAIT_FOR_ENABLE;
\r
261 if ((Tick64() - connect_started_tick) >= KEEP_RETRY_INTERVAL)
\r
266 Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);
\r
271 // 一定時間ごとにパケットデータを送受信する
\r
274 UINT64 last_packet_sent_time = 0;
\r
279 UCHAR buf[MAX_SIZE];
\r
283 AddSockSet(&set, s);
\r
285 Select(&set, KEEP_POLLING_INTERVAL, k->Cancel, NULL);
\r
287 ret = Recv(s, buf, sizeof(buf), false);
\r
298 if ((Tick64() - last_packet_sent_time) >= (UINT64)k->Interval)
\r
303 last_packet_sent_time = Tick64();
\r
305 b = NewKeepPacket(k->Server);
\r
307 ret = Send(s, b->Buf, b->Size, false);
\r
324 if (StrCmpi(k->ServerName, server_name) != 0 ||
\r
325 k->ServerPort != server_port || k->Enable == false ||
\r
333 if (changed || s == NULL)
\r
335 // 設定が変更された または 切断された
\r
339 goto WAIT_FOR_ENABLE;
\r
358 // ソケット作成が成功するまで試行する
\r
361 UINT64 connect_started_tick;
\r
362 bool changed = false;
\r
365 if (StrCmpi(k->ServerName, server_name) != 0 ||
\r
366 k->ServerPort != server_port || k->Enable == false ||
\r
367 k->UdpMode == false)
\r
376 goto WAIT_FOR_ENABLE;
\r
386 connect_started_tick = Tick64();
\r
389 if (GetIP(&dest_ip, server_name))
\r
391 // 名前解決に成功したら、次にソケットを作成
\r
400 // 作成失敗 設定が変更されるかタイムアウトするまで待機する
\r
411 if (StrCmpi(k->ServerName, server_name) != 0 ||
\r
412 k->ServerPort != server_port || k->Enable == false ||
\r
423 goto WAIT_FOR_ENABLE;
\r
426 if ((Tick64() - connect_started_tick) >= KEEP_RETRY_INTERVAL)
\r
431 Wait(k->HaltEvent, KEEP_POLLING_INTERVAL);
\r
435 // 一定時間ごとにパケットデータを送信する
\r
438 UINT64 last_packet_sent_time = 0;
\r
443 UCHAR buf[MAX_SIZE];
\r
449 AddSockSet(&set, s);
\r
451 Select(&set, KEEP_POLLING_INTERVAL, k->Cancel, NULL);
\r
454 ret = RecvFrom(s, &src_ip, &src_port, buf, sizeof(buf));
\r
455 if (ret == 0 && s->IgnoreRecvErr == false)
\r
465 if ((Tick64() - last_packet_sent_time) >= (UINT64)k->Interval)
\r
470 last_packet_sent_time = Tick64();
\r
472 b = NewKeepPacket(k->Server);
\r
474 ret = SendTo(s, &dest_ip, server_port, b->Buf, b->Size);
\r
477 if (ret == 0 && s->IgnoreSendErr == false)
\r
491 if (StrCmpi(k->ServerName, server_name) != 0 ||
\r
492 k->ServerPort != server_port || k->Enable == false ||
\r
493 k->UdpMode == false)
\r
500 if (changed || s == NULL)
\r
502 // 設定が変更された または 切断された
\r
506 goto WAIT_FOR_ENABLE;
\r
524 void StopKeep(KEEP *k)
\r
536 WaitThread(k->Thread, INFINITE);
\r
537 ReleaseThread(k->Thread);
\r
538 DeleteLock(k->lock);
\r
540 ReleaseCancel(k->Cancel);
\r
541 ReleaseEvent(k->HaltEvent);
\r
549 KEEP *k = ZeroMalloc(sizeof(KEEP));
\r
551 k->lock = NewLock();
\r
552 k->HaltEvent = NewEvent();
\r
553 k->Cancel = NewCancel();
\r
556 k->Thread = NewThread(KeepThread, k);
\r
562 CLIENT_AUTH *CopyClientAuth(CLIENT_AUTH *a)
\r
571 ret = ZeroMallocEx(sizeof(CLIENT_AUTH), true);
\r
573 ret->AuthType = a->AuthType;
\r
574 StrCpy(ret->Username, sizeof(ret->Username), a->Username);
\r
576 switch (a->AuthType)
\r
578 case CLIENT_AUTHTYPE_ANONYMOUS:
\r
582 case CLIENT_AUTHTYPE_PASSWORD:
\r
584 Copy(ret->HashedPassword, a->HashedPassword, SHA1_SIZE);
\r
587 case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
\r
589 StrCpy(ret->PlainPassword, sizeof(ret->PlainPassword), a->PlainPassword);
\r
592 case CLIENT_AUTHTYPE_CERT:
\r
594 ret->ClientX = CloneX(a->ClientX);
\r
595 ret->ClientK = CloneK(a->ClientK);
\r
598 case CLIENT_AUTHTYPE_SECURE:
\r
600 StrCpy(ret->SecurePublicCertName, sizeof(ret->SecurePublicCertName), a->SecurePublicCertName);
\r
601 StrCpy(ret->SecurePrivateKeyName, sizeof(ret->SecurePrivateKeyName), a->SecurePrivateKeyName);
\r
608 // 送信 FIFO にデータを書き込む (自動暗号化)
\r
609 void WriteSendFifo(SESSION *s, TCPSOCK *ts, void *data, UINT size)
\r
612 if (s == NULL || ts == NULL || data == NULL)
\r
619 Encrypt(ts->SendKey, data, data, size);
\r
622 WriteFifo(ts->SendFifo, data, size);
\r
625 // 受信 FIFO にデータを書き込む (自動解読)
\r
626 void WriteRecvFifo(SESSION *s, TCPSOCK *ts, void *data, UINT size)
\r
629 if (s == NULL || ts == NULL || data == NULL)
\r
636 Encrypt(ts->RecvKey, data, data, size);
\r
639 WriteFifo(ts->RecvFifo, data, size);
\r
643 UINT TcpSockRecv(SESSION *s, TCPSOCK *ts, void *data, UINT size)
\r
646 return Recv(ts->Sock, data, size, s->UseSSLDataEncryption);
\r
650 UINT TcpSockSend(SESSION *s, TCPSOCK *ts, void *data, UINT size)
\r
653 return Send(ts->Sock, data, size, s->UseSSLDataEncryption);
\r
656 // データを UDP パケットとして送信する
\r
657 void SendDataWithUDP(SOCK *s, CONNECTION *c)
\r
661 UINT64 dummy_64 = 0;
\r
662 UCHAR dummy_buf[16];
\r
663 UINT64 now = Tick64();
\r
665 bool force_flag = false;
\r
666 bool packet_sent = false;
\r
668 if (s == NULL || c == NULL)
\r
673 // 一時バッファをヒープから確保しておく
\r
674 if (c->RecvBuf == NULL)
\r
676 c->RecvBuf = Malloc(RECV_BUF_SIZE);
\r
680 if (c->Udp->NextKeepAliveTime == 0 || c->Udp->NextKeepAliveTime <= now)
\r
686 while ((c->SendBlocks->num_item > 0) || force_flag)
\r
692 force_flag = false;
\r
694 // 現在のキューからバッファを組み立てる
\r
697 // パケットヘッダ (16バイト) 分の領域を確保
\r
698 WriteBuf(b, dummy_buf, sizeof(dummy_buf));
\r
701 LockQueue(c->SendBlocks);
\r
707 if (b->Size > UDP_BUF_SIZE)
\r
711 block = GetNext(c->SendBlocks);
\r
717 if (block->Size != 0)
\r
719 WriteBufInt(b, block->Size);
\r
720 WriteBuf(b, block->Buf, block->Size);
\r
722 c->Session->TotalSendSize += (UINT64)block->SizeofData;
\r
723 c->Session->TotalSendSizeReal += (UINT64)block->Size;
\r
730 UnlockQueue(c->SendBlocks);
\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
740 // InsertQueue(c->Udp->BufferQueue, b);
\r
742 packet_sent = true;
\r
746 while (c->Udp->BufferQueue->num_item != 0)
\r
748 FIFO *f = c->Udp->BufferQueue->fifo;
\r
749 BUF **pb = (BUF**)(((UCHAR *)f->p) + f->pos);
\r
752 */ ret = SendTo(s, &c->Udp->ip, c->Udp->port, b->Buf, b->Size);
\r
753 if (ret == SOCK_LATER)
\r
759 if (ret != b->Size)
\r
761 if (s->IgnoreSendErr == false)
\r
764 Debug("******* SendTo Error !!!\n");
\r
770 // GetNext(c->Udp->BufferQueue);
\r
776 c->Udp->NextKeepAliveTime = now + (UINT64)GenNextKeepAliveSpan(c);
\r
780 // UDP パケットのデータをコネクションに書き込む
\r
781 void PutUDPPacketData(CONNECTION *c, void *data, UINT size)
\r
786 if (c == NULL || data == NULL)
\r
792 if (c->Protocol != CONNECTION_UDP)
\r
794 // UDP プロトコルは利用されていない
\r
800 WriteBuf(b, data, size);
\r
803 ReadBuf(b, sign, 4);
\r
806 if (Cmp(sign, SE_UDP_SIGN, 4) == 0)
\r
811 key32 = ReadBufInt(b);
\r
813 if (c->Session->SessionKey32 == key32)
\r
818 ReadBuf(b, &seq, sizeof(seq));
\r
819 seq = Endian64(seq);
\r
821 if ((UINT)(seq - c->Udp->RecvSeq - (UINT64)1))
\r
823 //Debug("** UDP Seq Lost %u\n", (UINT)(seq - c->Udp->RecvSeq - (UINT64)1));
\r
825 c->Udp->RecvSeq = seq;
\r
827 //Debug("SEQ: %I32u\n", seq);
\r
833 size = ReadBufInt(b);
\r
838 else if (size <= MAX_PACKET_SIZE)
\r
843 tmp = Malloc(size);
\r
844 if (ReadBuf(b, tmp, size) != size)
\r
851 block = NewBlock(tmp, size, 0);
\r
854 InsertReveicedBlockToQueue(c, block);
\r
859 c->Session->LastCommTime = Tick64();
\r
863 Debug("Invalid SessionKey: 0x%X\n", key32);
\r
871 void InsertReveicedBlockToQueue(CONNECTION *c, BLOCK *block)
\r
875 if (c == NULL || block == NULL)
\r
882 if (c->Protocol == CONNECTION_TCP)
\r
884 s->TotalRecvSizeReal += block->SizeofData;
\r
885 s->TotalRecvSize += block->Size;
\r
888 LockQueue(c->ReceivedBlocks);
\r
890 InsertQueue(c->ReceivedBlocks, block);
\r
892 UnlockQueue(c->ReceivedBlocks);
\r
895 // 次の Keep-Alive パケットまでの間隔を生成 (ネットワーク負荷減少のため乱数にする)
\r
896 UINT GenNextKeepAliveSpan(CONNECTION *c)
\r
905 a = c->Session->Timeout;
\r
906 b = rand() % (a / 2);
\r
912 // Keep-Alive パケットを送信する
\r
913 void SendKeepAlive(CONNECTION *c, TCPSOCK *ts)
\r
919 if (c == NULL || ts == NULL)
\r
924 size = rand() % MAX_KEEPALIVE_SIZE;
\r
925 num = KEEP_ALIVE_MAGIC;
\r
926 buf = MallocFast(size);
\r
928 for (i = 0;i < size;i++)
\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
939 c->Session->TotalSendSize += sizeof(UINT) * 2 + size;
\r
940 c->Session->TotalSendSizeReal += sizeof(UINT) * 2 + size;
\r
946 void ConnectionSend(CONNECTION *c)
\r
948 // このあたりは急いで実装したのでコードがあまり美しくない。
\r
952 TCPSOCK **tcpsocks;
\r
968 if (c->Protocol == CONNECTION_TCP)
\r
974 UINT num_available;
\r
975 LockList(tcp->TcpSockList);
\r
977 num = LIST_NUM(tcp->TcpSockList);
\r
978 tcpsocks = ToArrayEx(tcp->TcpSockList, true);
\r
980 UnlockList(tcp->TcpSockList);
\r
982 // 送信に使用するソケットを選択する
\r
983 // 遅延回数が最も少ないソケットを選出
\r
984 min_count = INFINITE;
\r
990 for (i = 0;i < num;i++)
\r
992 TCPSOCK *tcpsock = tcpsocks[i];
\r
993 if (tcpsock->Sock->Connected && tcpsock->Sock->AsyncMode &&
\r
994 IS_SEND_TCP_SOCK(tcpsock))
\r
997 if (now >= tcpsock->NextKeepAliveTime || tcpsock->NextKeepAliveTime == 0)
\r
1000 SendKeepAlive(c, tcpsock);
\r
1001 tcpsock->NextKeepAliveTime = now + (UINT64)GenNextKeepAliveSpan(c);
\r
1004 // 送信に利用可能なソケット数を計測する
\r
1011 for (i = 0;i < num;i++)
\r
1013 TCPSOCK *tcpsock = tcpsocks[i];
\r
1014 if (tcpsock->Sock->Connected && tcpsock->Sock->AsyncMode &&
\r
1015 IS_SEND_TCP_SOCK(tcpsock))
\r
1020 if (use_qos == false)
\r
1024 else if (num_available < 2)
\r
1028 else if (tcpsock != ts_hp)
\r
1035 if (tcpsock->LateCount <= min_count)
\r
1037 min_count = tcpsock->LateCount;
\r
1044 if (use_qos == false)
\r
1049 if (ts == NULL || ts_hp == NULL)
\r
1051 // 現在 送信可能なソケットが存在しない
\r
1059 for (j = 0;j < 2;j++)
\r
1063 q = c->SendBlocks2;
\r
1068 q = c->SendBlocks;
\r
1071 // 選択されたソケット ts に対して送信データを予約する
\r
1072 LockQueue(c->SendBlocks);
\r
1073 if (q->num_item != 0)
\r
1078 if (tss->SendFifo->size >= MAX((MAX_SEND_SOCKET_QUEUE_SIZE / s->MaxConnection), MIN_SEND_SOCKET_QUEUE_SIZE))
\r
1080 // 送信ソケットキューのサイズが超過
\r
1082 while (b = GetNext(q))
\r
1086 c->CurrentSendQueueSize -= b->Size;
\r
1093 bool update_keepalive_timer = false;
\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
1099 s->TotalSendSize += sizeof(UINT);
\r
1100 s->TotalSendSizeReal += sizeof(UINT);
\r
1102 while (b = GetNext(q))
\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
1110 c->CurrentSendQueueSize -= b->Size;
\r
1112 s->TotalSendSize += sizeof(UINT);
\r
1113 s->TotalSendSizeReal += sizeof(UINT);
\r
1116 PROBE_DATA2("WriteSendFifo data", b->Buf, b->Size);
\r
1117 WriteSendFifo(s, tss, b->Buf, b->Size);
\r
1119 s->TotalSendSize += b->SizeofData;
\r
1120 s->TotalSendSizeReal += b->Size;
\r
1122 update_keepalive_timer = true;
\r
1128 if (update_keepalive_timer)
\r
1130 // KeepAlive タイマを増加させる
\r
1131 tss->NextKeepAliveTime = now + (UINT64)GenNextKeepAliveSpan(c);
\r
1135 UnlockQueue(c->SendBlocks);
\r
1139 // 現在各ソケットに登録されている送信予約データを送信する
\r
1140 for (i = 0;i < num;i++)
\r
1145 if (ts->Sock->Connected == false)
\r
1147 s->LastTryAddConnectTime = Tick64();
\r
1149 LockList(tcp->TcpSockList);
\r
1151 // ソケットリストからこのソケットを削除する
\r
1152 Delete(tcp->TcpSockList, ts);
\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
1160 UnlockList(tcp->TcpSockList);
\r
1166 if (ts->SendFifo->size != 0)
\r
1169 UINT want_send_size;
\r
1170 // 1 バイト以上送信予定データが存在する場合のみ送信する
\r
1172 buf = (UCHAR *)ts->SendFifo->p + ts->SendFifo->pos;
\r
1173 want_send_size = ts->SendFifo->size;
\r
1175 PROBE_DATA2("TcpSockSend", buf, want_send_size);
\r
1176 size = TcpSockSend(s, ts, buf, want_send_size);
\r
1182 else if (size == SOCK_LATER)
\r
1185 ts->LateCount++; // 遅延カウンタのインクリメント
\r
1186 PROBE_STR("ts->LateCount++;");
\r
1190 // パケットが size だけ送信された
\r
1192 ReadFifo(ts->SendFifo, NULL, size);
\r
1193 if (size < want_send_size)
\r
1195 // 予定されたデータのすべてを送信することができなかった
\r
1198 char tmp[MAX_SIZE];
\r
1200 snprintf(tmp, sizeof(tmp), "size < want_send_size: %u < %u",
\r
1201 size, want_send_size);
\r
1205 #endif // USE_PROBE
\r
1209 // すべてのパケットの送信が完了した (キューが無くなった)
\r
1210 // ので、遅延カウンタをリセットする
\r
1211 ts->LateCount = 0;
\r
1213 PROBE_STR("TcpSockSend All Completed");
\r
1216 c->Session->LastCommTime = now;
\r
1225 else if (c->Protocol == CONNECTION_UDP)
\r
1228 UDP *udp = c->Udp;
\r
1229 SOCK *sock = NULL;
\r
1236 AddRef(sock->ref);
\r
1246 if ((udp->NextKeepAliveTime == 0 || udp->NextKeepAliveTime <= now) ||
\r
1247 (c->SendBlocks->num_item != 0) || (udp->BufferQueue->num_item != 0))
\r
1249 // 現在のキューを UDP で送信
\r
1250 SendDataWithUDP(sock, c);
\r
1256 ReleaseSock(sock);
\r
1259 else if (c->Protocol == CONNECTION_HUB_SECURE_NAT)
\r
1261 // SecureNAT セッション
\r
1262 SNAT *snat = s->SecureNAT;
\r
1263 VH *v = snat->Nat->Virtual;
\r
1265 LockQueue(c->SendBlocks);
\r
1268 UINT num_packet = 0;
\r
1270 while (block = GetNext(c->SendBlocks))
\r
1273 c->CurrentSendQueueSize -= block->Size;
\r
1274 VirtualPutPacket(v, block->Buf, block->Size);
\r
1278 if (num_packet != 0)
\r
1280 VirtualPutPacket(v, NULL, 0);
\r
1283 UnlockQueue(c->SendBlocks);
\r
1285 else if (c->Protocol == CONNECTION_HUB_LAYER3)
\r
1288 L3IF *f = s->L3If;
\r
1290 LockQueue(c->SendBlocks);
\r
1293 UINT num_packet = 0;
\r
1295 while (block = GetNext(c->SendBlocks))
\r
1298 c->CurrentSendQueueSize -= block->Size;
\r
1299 L3PutPacket(f, block->Buf, block->Size);
\r
1303 if (num_packet != 0)
\r
1305 L3PutPacket(f, NULL, 0);
\r
1308 UnlockQueue(c->SendBlocks);
\r
1310 else if (c->Protocol == CONNECTION_HUB_LINK_SERVER)
\r
1313 LINK *k = (LINK *)s->Link;
\r
1317 LockQueue(c->SendBlocks);
\r
1319 UINT num_blocks = 0;
\r
1320 LockQueue(k->SendPacketQueue);
\r
1324 // パケットキューをクライアントスレッドに転送する
\r
1325 while (block = GetNext(c->SendBlocks))
\r
1328 c->CurrentSendQueueSize -= block->Size;
\r
1329 InsertQueue(k->SendPacketQueue, block);
\r
1332 UnlockQueue(k->SendPacketQueue);
\r
1334 if (num_blocks != 0)
\r
1337 Cancel(k->ClientSession->Cancel1);
\r
1340 UnlockQueue(c->SendBlocks);
\r
1343 else if (c->Protocol == CONNECTION_HUB_BRIDGE)
\r
1346 BRIDGE *b = s->Bridge;
\r
1352 LockQueue(c->SendBlocks);
\r
1355 UINT num_packet = c->SendBlocks->num_item; // パケット数
\r
1357 if (num_packet != 0)
\r
1360 void **datas = MallocFast(sizeof(void *) * num_packet);
\r
1361 UINT *sizes = MallocFast(sizeof(UINT *) * num_packet);
\r
1365 while (block = GetNext(c->SendBlocks))
\r
1367 datas[i] = block->Buf;
\r
1368 sizes[i] = block->Size;
\r
1370 if (block->Size > 1514)
\r
1372 NormalizeEthMtu(b, c, block->Size);
\r
1375 c->CurrentSendQueueSize -= block->Size;
\r
1381 EthPutPackets(b->Eth, num_packet, datas, sizes);
\r
1387 UnlockQueue(c->SendBlocks);
\r
1394 void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
\r
1396 // このあたりは急いで実装したのでコードがあまり美しくない。
\r
1400 TCPSOCK **tcpsocks;
\r
1405 UINT num_delayed = 0;
\r
1406 bool no_spinlock_for_delay = false;
\r
1413 PROBE_STR("ConnectionReceive");
\r
1417 if (s->Hub != NULL)
\r
1419 no_spinlock_for_delay = s->Hub->Option->NoSpinLockForPacketDelay;
\r
1424 if (c->RecvBuf == NULL)
\r
1426 c->RecvBuf = Malloc(RECV_BUF_SIZE);
\r
1431 if (c->Protocol == CONNECTION_TCP)
\r
1434 TCP *tcp = c->Tcp;
\r
1436 // コネクション切断間隔が指定されている場合はコネクションの切断を行う
\r
1437 if (s->ServerMode == false)
\r
1439 if (s->ClientOption->ConnectionDisconnectSpan != 0)
\r
1441 LockList(tcp->TcpSockList);
\r
1444 for (i = 0;i < LIST_NUM(tcp->TcpSockList);i++)
\r
1446 TCPSOCK *ts = LIST_DATA(tcp->TcpSockList, i);
\r
1447 if (ts->DisconnectTick != 0 &&
\r
1448 ts->DisconnectTick <= now)
\r
1450 Debug("ts->DisconnectTick <= now\n");
\r
1451 Disconnect(ts->Sock);
\r
1455 UnlockList(tcp->TcpSockList);
\r
1459 if (s->HalfConnection && (s->ServerMode == false))
\r
1461 // 現在の TCP コネクションの方向を調べ、
\r
1462 // 一方向しか無く かつコネクション数が限界の場合は
\r
1464 LockList(tcp->TcpSockList);
\r
1469 num = LIST_NUM(tcp->TcpSockList);
\r
1470 if (num >= s->MaxConnection)
\r
1473 for (i = 0;i < num;i++)
\r
1475 ts = LIST_DATA(tcp->TcpSockList, i);
\r
1476 if (ts->Direction == TCP_SERVER_TO_CLIENT)
\r
1485 if (s2c == 0 || c2s == 0)
\r
1488 Disconnect(ts->Sock);
\r
1489 Debug("Disconnect (s2c=%u, c2s=%u)\n", s2c, c2s);
\r
1493 UnlockList(tcp->TcpSockList);
\r
1497 InitSockSet(&set);
\r
1498 LockList(tcp->TcpSockList);
\r
1500 num = LIST_NUM(tcp->TcpSockList);
\r
1501 tcpsocks = ToArrayEx(tcp->TcpSockList, true);
\r
1503 UnlockList(tcp->TcpSockList);
\r
1505 for (i = 0;i < num;i++)
\r
1507 AddSockSet(&set, tcpsocks[i]->Sock);
\r
1511 time = SELECT_TIME;
\r
1512 if (s->VirtualHost)
\r
1514 time = MIN(time, SELECT_TIME_FOR_NAT);
\r
1516 time = MIN(time, GetNextDelayedPacketTickDiff(s));
\r
1517 num_delayed = LIST_NUM(s->DelayedPacketList);
\r
1519 PROBE_STR("ConnectionReceive: Select 0");
\r
1521 if (s->Flag1 != set.NumSocket)
\r
1523 Select(&set, (num_delayed == 0 ? time : 1), c1, c2);
\r
1524 s->Flag1 = set.NumSocket;
\r
1528 if (no_spinlock_for_delay || time >= 50 || num_delayed == false)
\r
1530 Select(&set, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);
\r
1531 s->Flag1 = set.NumSocket;
\r
1539 PROBE_STR("ConnectionReceive: Select 1");
\r
1541 // TCP ソケットに到着しているデータをすべて読み込む
\r
1542 for (i = 0;i < num;i++)
\r
1544 TCPSOCK *ts = tcpsocks[i];
\r
1545 if (ts->WantSize == 0)
\r
1547 // 最初に必ず sizeof(UINT) だけ読み込む
\r
1548 ts->WantSize = sizeof(UINT);
\r
1553 size = TcpSockRecv(s, ts, buf, RECV_BUF_SIZE);
\r
1556 DISCONNECT_THIS_TCP:
\r
1557 s->LastTryAddConnectTime = Tick64();
\r
1559 LockList(tcp->TcpSockList);
\r
1561 // ソケットリストからこのソケットを削除する
\r
1562 Delete(tcp->TcpSockList, ts);
\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
1570 UnlockList(tcp->TcpSockList);
\r
1574 else if (size == SOCK_LATER)
\r
1577 if (IS_RECV_TCP_SOCK(ts))
\r
1579 if ((now > ts->LastCommTime) && ((now - ts->LastCommTime) >= ((UINT64)s->Timeout)))
\r
1581 // このコネクションはタイムアウトした
\r
1582 Debug("Connection %u Timeouted.\n", i);
\r
1583 goto DISCONNECT_THIS_TCP;
\r
1590 ts->LastCommTime = now;
\r
1591 c->Session->LastCommTime = now;
\r
1593 // データが受信できたので FIFO に書き込む
\r
1594 PROBE_DATA2("WriteRecvFifo", buf, size);
\r
1595 WriteRecvFifo(s, ts, buf, size);
\r
1597 // 受信バッファがいっぱいになったら受信をやめる
\r
1598 if (ts->RecvFifo->size < MAX_SEND_SOCKET_QUEUE_SIZE)
\r
1604 // FIFO に書き込まれたデータを処理する
\r
1605 while (ts->RecvFifo->size >= ts->WantSize)
\r
1611 // すでに十分な量のデータが格納されている
\r
1613 buf = (UCHAR *)ts->RecvFifo->p + ts->RecvFifo->pos;
\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
1626 s->TotalRecvSize += sizeof(UINT);
\r
1627 s->TotalRecvSizeReal += sizeof(UINT);
\r
1629 ts->CurrentPacketNum = 0;
\r
1630 if (ts->NextBlockNum != 0)
\r
1632 if (ts->NextBlockNum == KEEP_ALIVE_MAGIC)
\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
1650 // おかしなデータサイズを受信した
\r
1652 Debug("%s %u sz > (MAX_PACKET_SIZE * 2)\n", __FILE__, __LINE__);
\r
1653 Disconnect(ts->Sock);
\r
1655 ts->NextBlockSize = MIN(sz, MAX_PACKET_SIZE * 2);
\r
1656 ReadFifo(ts->RecvFifo, NULL, sizeof(UINT));
\r
1658 s->TotalRecvSize += sizeof(UINT);
\r
1659 s->TotalRecvSizeReal += sizeof(UINT);
\r
1661 ts->WantSize = ts->NextBlockSize;
\r
1662 if (ts->WantSize != 0)
\r
1669 ts->WantSize = sizeof(UINT);
\r
1670 ts->CurrentPacketNum++;
\r
1671 if (ts->CurrentPacketNum >= ts->NextBlockNum)
\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
1688 if (block->Size > MAX_PACKET_SIZE)
\r
1696 InsertReveicedBlockToQueue(c, block);
\r
1699 if (ts->CurrentPacketNum >= ts->NextBlockNum)
\r
1701 // すべてのデータブロックの受信が完了
\r
1706 // 次のデータブロックサイズを受信
\r
1712 // Keep-Alive パケットサイズ
\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
1719 // おかしなデータサイズを受信した
\r
1721 Debug("%s %u sz > MAX_KEEPALIVE_SIZE\n", __FILE__, __LINE__);
\r
1722 Disconnect(ts->Sock);
\r
1724 ts->NextBlockSize = MIN(sz, MAX_KEEPALIVE_SIZE);
\r
1725 ReadFifo(ts->RecvFifo, NULL, sizeof(UINT));
\r
1727 s->TotalRecvSize += sizeof(UINT);
\r
1728 s->TotalRecvSizeReal += sizeof(UINT);
\r
1730 ts->WantSize = sz;
\r
1734 // Keep-Alive パケット本体
\r
1735 //Debug("KeepAlive Recved.\n");
\r
1737 sz = ts->NextBlockSize;
\r
1738 PROBE_DATA2("ReadFifo 4", NULL, 0);
\r
1739 ReadFifo(ts->RecvFifo, NULL, sz);
\r
1741 s->TotalRecvSize += sz;
\r
1742 s->TotalRecvSizeReal += sz;
\r
1744 ts->WantSize = sizeof(UINT);
\r
1752 else if (c->Protocol == CONNECTION_UDP)
\r
1755 UDP *udp = c->Udp;
\r
1756 SOCK *sock = NULL;
\r
1758 if (s->ServerMode == false)
\r
1762 if (c->Udp->s != NULL)
\r
1767 AddRef(sock->ref);
\r
1773 InitSockSet(&set);
\r
1777 AddSockSet(&set, sock);
\r
1780 Select(&set, SELECT_TIME, c1, c2);
\r
1792 size = RecvFrom(sock, &ip, &port, buf, RECV_BUF_SIZE);
\r
1793 if (size == 0 && sock->IgnoreRecvErr == false)
\r
1795 Debug("UDP Socket Disconnected.\n");
\r
1798 ReleaseSock(udp->s);
\r
1804 else if (size == SOCK_LATER)
\r
1812 PutUDPPacketData(c, buf, size);
\r
1820 Release(sock->ref);
\r
1825 Select(NULL, SELECT_TIME, c1, c2);
\r
1828 else if (c->Protocol == CONNECTION_HUB_SECURE_NAT)
\r
1830 SNAT *snat = c->Session->SecureNAT;
\r
1831 VH *v = snat->Nat->Virtual;
\r
1835 UINT select_wait_time = SELECT_TIME_FOR_NAT;
\r
1837 if (snat->Nat != NULL && snat->Nat->Option.UseNat == false)
\r
1839 select_wait_time = SELECT_TIME;
\r
1843 if (snat->Nat != NULL)
\r
1845 LockList(v->NatTable);
\r
1847 if (LIST_NUM(v->NatTable) == 0 && LIST_NUM(v->ArpWaitTable) == 0)
\r
1849 select_wait_time = SELECT_TIME;
\r
1852 UnlockList(v->NatTable);
\r
1856 select_wait_time = MIN(select_wait_time, GetNextDelayedPacketTickDiff(s));
\r
1857 num_delayed = LIST_NUM(s->DelayedPacketList);
\r
1859 if (no_spinlock_for_delay || select_wait_time >= 50 || num_delayed == false)
\r
1861 Select(NULL, (num_delayed == 0 ? select_wait_time :
\r
1862 (select_wait_time > 100 ? (select_wait_time - 100) : 1)), c1, c2);
\r
1871 // 仮想マシンからパケットを受信する
\r
1872 while (size = VirtualGetNextPacket(v, &data))
\r
1877 block = NewBlock(data, size, 0);
\r
1878 if (block->Size > MAX_PACKET_SIZE)
\r
1886 InsertReveicedBlockToQueue(c, block);
\r
1889 if (num >= MAX_SEND_SOCKET_QUEUE_NUM)
\r
1896 else if (c->Protocol == CONNECTION_HUB_LINK_SERVER)
\r
1899 // 単純に Cancel を待つだけ
\r
1900 if (c->SendBlocks->num_item == 0)
\r
1902 UINT time = SELECT_TIME;
\r
1904 time = MIN(time, GetNextDelayedPacketTickDiff(s));
\r
1905 num_delayed = LIST_NUM(s->DelayedPacketList);
\r
1907 if (no_spinlock_for_delay || time >= 50 || num_delayed == false)
\r
1909 Select(NULL, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);
\r
1917 else if (c->Protocol == CONNECTION_HUB_LAYER3)
\r
1919 // Layer-3 スイッチ セッション
\r
1920 L3IF *f = s->L3If;
\r
1921 UINT size, num = 0;
\r
1924 if (f->SendQueue->num_item == 0)
\r
1926 UINT time = SELECT_TIME_FOR_NAT;
\r
1928 if (f->ArpWaitTable != NULL)
\r
1930 LockList(f->ArpWaitTable);
\r
1932 if (LIST_NUM(f->ArpWaitTable) == 0)
\r
1934 time = SELECT_TIME;
\r
1937 UnlockList(f->ArpWaitTable);
\r
1940 time = MIN(time, GetNextDelayedPacketTickDiff(s));
\r
1941 num_delayed = LIST_NUM(s->DelayedPacketList);
\r
1943 if (no_spinlock_for_delay || time >= 50 || num_delayed == false)
\r
1945 Select(NULL, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);
\r
1954 while (size = L3GetNextPacket(f, &data))
\r
1956 BLOCK *block = NewBlock(data, size, 0);
\r
1957 if (block->Size > MAX_PACKET_SIZE)
\r
1963 InsertReveicedBlockToQueue(c, block);
\r
1967 if (num >= MAX_SEND_SOCKET_QUEUE_NUM)
\r
1973 else if (c->Protocol == CONNECTION_HUB_BRIDGE)
\r
1975 BRIDGE *b = c->Session->Bridge;
\r
1983 bool check_device_num = false;
\r
1984 UINT time = SELECT_TIME;
\r
1986 time = MIN(time, GetNextDelayedPacketTickDiff(s));
\r
1987 num_delayed = LIST_NUM(s->DelayedPacketList);
\r
1990 if (no_spinlock_for_delay || time >= 50 || num_delayed == false)
\r
1992 Select(NULL, (num_delayed == 0 ? time : (time > 100 ? (time - 100) : 1)), c1, c2);
\r
1999 if ((b->LastNumDeviceCheck + BRIDGE_NUM_DEVICE_CHECK_SPAN) <= Tick64())
\r
2001 check_device_num = true;
\r
2002 b->LastNumDeviceCheck = Tick64();
\r
2005 // ブリッジから次のパケットを取得する
\r
2008 if (check_device_num && b->LastNumDevice != GetEthDeviceHash())
\r
2014 ret = EthGetPacket(b->Eth, &data);
\r
2018 if (b->Eth != NULL && b->Eth->LoopbackBlock)
\r
2020 // ブリッジにおける eth デバイスがループバックパケットを遮断
\r
2021 // する能力がある場合は CheckMac ポリシーを無効にする
\r
2022 if (c->Session != NULL && c->Session->Policy != NULL)
\r
2024 c->Session->Policy->CheckMac = false;
\r
2027 #endif // OS_WIN32
\r
2029 if (ret == INFINITE)
\r
2031 // エラー発生 ブリッジを停止させる
\r
2034 b->Active = false;
\r
2035 ReleaseCancel(s->Cancel2);
\r
2036 s->Cancel2 = NULL;
\r
2038 HLog(s->Hub, "LH_BRIDGE_2", s->Name, b->Name);
\r
2039 Debug("Bridge Device Error.\n");
\r
2043 else if (ret == 0)
\r
2051 BLOCK *block = NewBlock(data, ret, 0);
\r
2053 PROBE_DATA2("ConnectionReceive: NewBlock", data, ret);
\r
2057 NormalizeEthMtu(b, c, ret);
\r
2060 if (block->Size > MAX_PACKET_SIZE)
\r
2067 InsertReveicedBlockToQueue(c, block);
\r
2070 if (num >= MAX_SEND_SOCKET_QUEUE_NUM)
\r
2082 Select(NULL, SELECT_TIME, c1, NULL);
\r
2084 if (b->LastBridgeTry == 0 || (b->LastBridgeTry + BRIDGE_TRY_SPAN) <= Tick64())
\r
2086 b->LastBridgeTry = Tick64();
\r
2088 // Ethernet デバイスを開こうとしてみる
\r
2089 e = OpenEth(b->Name, b->Local, b->TapMode, b->TapMacAddress);
\r
2095 b->LastNumDeviceCheck = Tick64();
\r
2096 b->LastNumDevice = GetEthDeviceHash();
\r
2098 Debug("Bridge Open Succeed.\n");
\r
2100 HLog(c->Session->Hub, "LH_BRIDGE_1", c->Session->Name, b->Name);
\r
2102 s->Cancel2 = EthGetCancel(b->Eth);
\r
2109 // Ethernet デバイスの MTU を正規化する
\r
2110 void NormalizeEthMtu(BRIDGE *b, CONNECTION *c, UINT packet_size)
\r
2113 if (packet_size == 0 || b == NULL || c == NULL)
\r
2118 // 現在の MTU を超えるパケットの場合は MTU を引き上げる
\r
2119 if (EthIsChangeMtuSupported(b->Eth))
\r
2121 UINT currentMtu = EthGetMtu(b->Eth);
\r
2122 if (currentMtu != 0)
\r
2124 if (packet_size > currentMtu)
\r
2126 bool ok = EthSetMtu(b->Eth, packet_size);
\r
2130 HLog(c->Session->Hub, "LH_SET_MTU", c->Session->Name,
\r
2131 b->Name, currentMtu, packet_size, packet_size);
\r
2135 UINT64 now = Tick64();
\r
2137 if (b->LastChangeMtuError == 0 ||
\r
2138 now >= (b->LastChangeMtuError + 60000ULL))
\r
2140 HLog(c->Session->Hub, "LH_SET_MTU_ERROR", c->Session->Name,
\r
2141 b->Name, currentMtu, packet_size, packet_size);
\r
2143 b->LastChangeMtuError = now;
\r
2152 void FreeBlock(BLOCK *b)
\r
2165 BLOCK *NewBlock(void *data, UINT size, int compress)
\r
2174 b = ZeroMallocFast(sizeof(BLOCK));
\r
2176 if (compress == 0)
\r
2179 b->Compressed = FALSE;
\r
2182 b->SizeofData = size;
\r
2184 else if (compress == 1)
\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
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
2216 TCPSOCK *NewTcpSock(SOCK *s)
\r
2225 ts = ZeroMalloc(sizeof(TCPSOCK));
\r
2230 ts->RecvFifo = NewFifo();
\r
2231 ts->SendFifo = NewFifo();
\r
2232 ts->LastCommTime = Tick64();
\r
2235 SetTimeout(s, TIMEOUT_INFINITE);
\r
2240 // TCP ソケット用暗号化鍵の設定
\r
2241 void InitTcpSockRc4Key(TCPSOCK *ts, bool server_mode)
\r
2243 RC4_KEY_PAIR *pair;
\r
2251 pair = &ts->Rc4KeyPair;
\r
2253 c1 = NewCrypt(pair->ClientToServerKey, sizeof(pair->ClientToServerKey));
\r
2254 c2 = NewCrypt(pair->ServerToClientKey, sizeof(pair->ServerToClientKey));
\r
2269 void FreeTcpSock(TCPSOCK *ts)
\r
2277 Disconnect(ts->Sock);
\r
2278 ReleaseSock(ts->Sock);
\r
2279 ReleaseFifo(ts->RecvFifo);
\r
2280 ReleaseFifo(ts->SendFifo);
\r
2284 FreeCrypt(ts->SendKey);
\r
2288 FreeCrypt(ts->RecvKey);
\r
2294 // コネクションのトンネリングモードを終了する
\r
2295 void EndTunnelingMode(CONNECTION *c)
\r
2304 if (c->Protocol == CONNECTION_TCP)
\r
2307 DisconnectTcpSockets(c);
\r
2312 DisconnectUDPSockets(c);
\r
2316 // コネクションをトンネリングモードに移行させる
\r
2317 void StartTunnelingMode(CONNECTION *c)
\r
2333 if (c->Protocol == CONNECTION_TCP)
\r
2338 ts = NewTcpSock(s);
\r
2340 if (c->ServerMode == false)
\r
2342 if (c->Session->ClientOption->ConnectionDisconnectSpan != 0)
\r
2344 ts->DisconnectTick = Tick64() + c->Session->ClientOption->ConnectionDisconnectSpan * (UINT64)1000;
\r
2348 LockList(tcp->TcpSockList);
\r
2350 Add(tcp->TcpSockList, ts);
\r
2352 UnlockList(tcp->TcpSockList);
\r
2354 c->FirstSock = NULL;
\r
2360 Copy(&ip, &s->RemoteIP, sizeof(IP));
\r
2361 // この時点で TCP コネクションは切断してよい
\r
2362 c->FirstSock = NULL;
\r
2367 c->Udp = ZeroMalloc(sizeof(UDP));
\r
2369 if (c->ServerMode)
\r
2373 AddUDPEntry(c->Cedar, c->Session);
\r
2378 port = c->Session->ClientOption->PortUDP;
\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
2387 c->Udp->BufferQueue = NewQueue();
\r
2391 // 新しいコネクションを受け付ける関数
\r
2392 void ConnectionAccept(CONNECTION *c)
\r
2404 Debug("ConnectionAccept()\n");
\r
2410 Dec(c->Cedar->AcceptingSockets);
\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
2416 SetTimeout(s, CONNECTING_TIMEOUT);
\r
2421 if (c->Cedar->CipherList != NULL)
\r
2423 SetWantToUseCipher(s, c->Cedar->CipherList);
\r
2426 x = CloneX(c->Cedar->ServerX);
\r
2427 k = CloneK(c->Cedar->ServerK);
\r
2432 Debug("StartSSL()\n");
\r
2433 if (StartSSL(s, x, k) == false)
\r
2436 Debug("Failed to StartSSL.\n");
\r
2445 SLog(c->Cedar, "LS_SSL_START", c->Name, s->CipherName);
\r
2448 if (ServerAccept(c) == false)
\r
2451 Debug("ServerAccept Failed. Err = %u\n", c->Err);
\r
2455 if (c->flag1 == false)
\r
2457 Debug("%s %u c->flag1 == false\n", __FILE__, __LINE__);
\r
2460 DelConnection(c->Cedar, c);
\r
2465 Debug("ConnectionAccept() Error.\n");
\r
2467 DelConnection(c->Cedar, c);
\r
2471 // 現在動作しているすべての追加コネクションを張るスレッドを中断する
\r
2472 void StopAllAdditionalConnectThread(CONNECTION *c)
\r
2478 if (c == NULL || c->ServerMode != false)
\r
2484 LockList(c->ConnectingSocks);
\r
2486 num = LIST_NUM(c->ConnectingSocks);
\r
2487 socks = ToArray(c->ConnectingSocks);
\r
2488 DeleteAll(c->ConnectingSocks);
\r
2490 UnlockList(c->ConnectingSocks);
\r
2491 for (i = 0;i < num;i++)
\r
2493 Disconnect(socks[i]);
\r
2494 ReleaseSock(socks[i]);
\r
2499 LockList(c->ConnectingThreads);
\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
2506 UnlockList(c->ConnectingThreads);
\r
2507 for (i = 0;i < num;i++)
\r
2509 WaitThread(threads[i], INFINITE);
\r
2510 ReleaseThread(threads[i]);
\r
2516 void StopConnection(CONNECTION *c, bool no_wait)
\r
2524 Debug("Stop Connection: %s\n", c->Name);
\r
2528 Disconnect(c->FirstSock);
\r
2530 if (no_wait == false)
\r
2533 WaitThread(c->Thread, INFINITE);
\r
2537 // UDP ソケットをすべて閉じる
\r
2538 void DisconnectUDPSockets(CONNECTION *c)
\r
2545 if (c->Protocol != CONNECTION_UDP)
\r
2551 if (c->ServerMode)
\r
2553 DelUDPEntry(c->Cedar, c->Session);
\r
2557 if (c->Udp != NULL)
\r
2559 if (c->Udp->s != NULL)
\r
2561 ReleaseSock(c->Udp->s);
\r
2563 if (c->Udp->BufferQueue != NULL)
\r
2567 while (b = GetNext(c->Udp->BufferQueue))
\r
2571 ReleaseQueue(c->Udp->BufferQueue);
\r
2577 if (c->FirstSock != NULL)
\r
2579 Disconnect(c->FirstSock);
\r
2580 ReleaseSock(c->FirstSock);
\r
2581 c->FirstSock = NULL;
\r
2585 // TCP コネクションをすべて閉じる
\r
2586 void DisconnectTcpSockets(CONNECTION *c)
\r
2590 TCPSOCK **tcpsocks;
\r
2596 if (c->Protocol != CONNECTION_TCP)
\r
2602 LockList(tcp->TcpSockList);
\r
2604 tcpsocks = ToArray(tcp->TcpSockList);
\r
2605 num = LIST_NUM(tcp->TcpSockList);
\r
2606 DeleteAll(tcp->TcpSockList);
\r
2608 UnlockList(tcp->TcpSockList);
\r
2612 Debug("--- SOCKET STATUS ---\n");
\r
2613 for (i = 0;i < num;i++)
\r
2615 TCPSOCK *ts = tcpsocks[i];
\r
2616 Debug(" SOCK %2u: %u\n", i, ts->Sock->SendSize);
\r
2625 void CleanupConnection(CONNECTION *c)
\r
2634 DeleteLock(c->lock);
\r
2635 ReleaseCedar(c->Cedar);
\r
2637 switch (c->Protocol)
\r
2639 case CONNECTION_TCP:
\r
2640 // TCP コネクションリストの解放
\r
2641 DisconnectTcpSockets(c);
\r
2644 case CONNECTION_UDP:
\r
2648 ReleaseList(c->Tcp->TcpSockList);
\r
2651 ReleaseSock(c->FirstSock);
\r
2652 c->FirstSock = NULL;
\r
2654 ReleaseThread(c->Thread);
\r
2657 // すべての送信ブロックと受信ブロックを解放
\r
2658 if (c->SendBlocks)
\r
2660 LockQueue(c->SendBlocks);
\r
2663 while (b = GetNext(c->SendBlocks))
\r
2668 UnlockQueue(c->SendBlocks);
\r
2670 if (c->SendBlocks2)
\r
2672 LockQueue(c->SendBlocks2);
\r
2675 while (b = GetNext(c->SendBlocks2))
\r
2680 UnlockQueue(c->SendBlocks2);
\r
2682 if (c->ReceivedBlocks)
\r
2684 LockQueue(c->ReceivedBlocks);
\r
2687 while (b = GetNext(c->ReceivedBlocks))
\r
2692 UnlockQueue(c->ReceivedBlocks);
\r
2695 if (c->ConnectingThreads)
\r
2698 LockList(c->ConnectingThreads);
\r
2700 num = LIST_NUM(c->ConnectingThreads);
\r
2701 threads = ToArray(c->ConnectingThreads);
\r
2702 for (i = 0;i < num;i++)
\r
2704 ReleaseThread(threads[i]);
\r
2708 UnlockList(c->ConnectingThreads);
\r
2709 ReleaseList(c->ConnectingThreads);
\r
2712 if (c->ConnectingSocks)
\r
2715 LockList(c->ConnectingSocks);
\r
2717 num = LIST_NUM(c->ConnectingSocks);
\r
2718 socks = ToArray(c->ConnectingSocks);
\r
2719 for (i = 0;i < num;i++)
\r
2721 Disconnect(socks[i]);
\r
2722 ReleaseSock(socks[i]);
\r
2726 UnlockList(c->ConnectingSocks);
\r
2727 ReleaseList(c->ConnectingSocks);
\r
2735 if (c->ServerX != NULL)
\r
2737 FreeX(c->ServerX);
\r
2740 if (c->ClientX != NULL)
\r
2742 FreeX(c->ClientX);
\r
2745 ReleaseQueue(c->ReceivedBlocks);
\r
2746 ReleaseQueue(c->SendBlocks);
\r
2747 ReleaseQueue(c->SendBlocks2);
\r
2749 DeleteCounter(c->CurrentNumConnection);
\r
2751 if (c->CipherName != NULL)
\r
2753 Free(c->CipherName);
\r
2760 void ReleaseConnection(CONNECTION *c)
\r
2768 if (Release(c->ref) == 0)
\r
2770 CleanupConnection(c);
\r
2775 int CompareConnection(void *p1, void *p2)
\r
2777 CONNECTION *c1, *c2;
\r
2778 if (p1 == NULL || p2 == NULL)
\r
2782 c1 = *(CONNECTION **)p1;
\r
2783 c2 = *(CONNECTION **)p2;
\r
2784 if (c1 == NULL || c2 == NULL)
\r
2789 return StrCmpi(c1->Name, c2->Name);
\r
2793 CONNECTION *NewServerConnection(CEDAR *cedar, SOCK *s, THREAD *t)
\r
2797 if (cedar == NULL)
\r
2802 c = ZeroMalloc(sizeof(CONNECTION));
\r
2803 c->ConnectedTick = Tick64();
\r
2804 c->lock = NewLock();
\r
2805 c->ref = NewRef();
\r
2807 AddRef(c->Cedar->ref);
\r
2808 c->Protocol = CONNECTION_TCP;
\r
2809 c->Type = CONNECTION_TYPE_INIT;
\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
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
2824 c->CurrentNumConnection = NewCounter();
\r
2825 Inc(c->CurrentNumConnection);
\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
2832 if (s != NULL && s->RemoteX != NULL)
\r
2834 c->ServerX = CloneX(s->RemoteX);
\r
2838 c->ReceivedBlocks = NewQueue();
\r
2839 c->SendBlocks = NewQueue();
\r
2840 c->SendBlocks2 = NewQueue();
\r
2845 // クライアントコネクションの作成
\r
2846 CONNECTION *NewClientConnection(SESSION *s)
\r
2848 return NewClientConnectionEx(s, NULL, 0, 0);
\r
2850 CONNECTION *NewClientConnectionEx(SESSION *s, char *client_str, UINT client_ver, UINT client_build)
\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
2864 c->Protocol = CONNECTION_TCP;
\r
2865 c->Tcp = ZeroMalloc(sizeof(TCP));
\r
2866 c->Tcp->TcpSockList = NewList(NULL);
\r
2871 c->Protocol = CONNECTION_UDP;
\r
2873 c->ServerMode = false;
\r
2874 c->Status = CONNECTION_STATUS_CONNECTING;
\r
2875 c->Name = CopyStr("CLIENT_CONNECTION");
\r
2877 c->CurrentNumConnection = NewCounter();
\r
2878 Inc(c->CurrentNumConnection);
\r
2880 c->ConnectingThreads = NewList(NULL);
\r
2881 c->ConnectingSocks = NewList(NULL);
\r
2883 if (client_str == NULL)
\r
2885 c->ClientVer = s->Cedar->Version;
\r
2886 c->ClientBuild = s->Cedar->Build;
\r
2888 if (c->Session->VirtualHost == false)
\r
2890 if (c->Session->LinkModeClient == false)
\r
2892 StrCpy(c->ClientStr, sizeof(c->ClientStr), CEDAR_CLIENT_STR);
\r
2896 StrCpy(c->ClientStr, sizeof(c->ClientStr), CEDAR_SERVER_LINK_STR);
\r
2901 StrCpy(c->ClientStr, sizeof(c->ClientStr), CEDAR_ROUTER_STR);
\r
2906 c->ClientVer = client_ver;
\r
2907 c->ClientBuild = client_build;
\r
2908 StrCpy(c->ClientStr, sizeof(c->ClientStr), client_str);
\r
2912 StrCpy(c->ServerName, sizeof(c->ServerName), s->ClientOption->Hostname);
\r
2913 c->ServerPort = s->ClientOption->Port;
\r
2916 c->DontUseTls1 = s->ClientOption->NoTls1;
\r
2919 c->ReceivedBlocks = NewQueue();
\r
2920 c->SendBlocks = NewQueue();
\r
2921 c->SendBlocks2 = NewQueue();
\r