ooxml_crypt 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +58 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/ext/ooxml_crypt/extconf.rb +18 -0
- data/ext/ooxml_crypt/ooxml_crypt.c +27 -0
- data/ext/ooxml_crypt/ooxml_crypt.h +7 -0
- data/lib/ooxml_crypt/version.rb +5 -0
- data/lib/ooxml_crypt.rb +75 -0
- data/vendor/cybozulib/.github/workflows/main.yml +12 -0
- data/vendor/cybozulib/.gitignore +5 -0
- data/vendor/cybozulib/CMakeLists.txt +6 -0
- data/vendor/cybozulib/COPYRIGHT +27 -0
- data/vendor/cybozulib/Makefile +26 -0
- data/vendor/cybozulib/bin/libeay32.dll +0 -0
- data/vendor/cybozulib/bin/libmecab.dll +0 -0
- data/vendor/cybozulib/bin/ssleay32.dll +0 -0
- data/vendor/cybozulib/common.mk +116 -0
- data/vendor/cybozulib/common.props +25 -0
- data/vendor/cybozulib/cybozulib.sln +286 -0
- data/vendor/cybozulib/debug.props +14 -0
- data/vendor/cybozulib/include/cybozu/array.hpp +197 -0
- data/vendor/cybozulib/include/cybozu/atoi.hpp +238 -0
- data/vendor/cybozulib/include/cybozu/atomic.hpp +146 -0
- data/vendor/cybozulib/include/cybozu/base64.hpp +210 -0
- data/vendor/cybozulib/include/cybozu/benchmark.hpp +212 -0
- data/vendor/cybozulib/include/cybozu/bfd.hpp +105 -0
- data/vendor/cybozulib/include/cybozu/bit_operation.hpp +139 -0
- data/vendor/cybozulib/include/cybozu/bitvector.hpp +358 -0
- data/vendor/cybozulib/include/cybozu/condition_variable.hpp +113 -0
- data/vendor/cybozulib/include/cybozu/condition_variable_cs.hpp +74 -0
- data/vendor/cybozulib/include/cybozu/config.hpp +392 -0
- data/vendor/cybozulib/include/cybozu/critical_section.hpp +60 -0
- data/vendor/cybozulib/include/cybozu/crypto.hpp +321 -0
- data/vendor/cybozulib/include/cybozu/csucvector.hpp +624 -0
- data/vendor/cybozulib/include/cybozu/csv.hpp +294 -0
- data/vendor/cybozulib/include/cybozu/data_type.hpp +27 -0
- data/vendor/cybozulib/include/cybozu/endian.hpp +224 -0
- data/vendor/cybozulib/include/cybozu/env.hpp +63 -0
- data/vendor/cybozulib/include/cybozu/event.hpp +122 -0
- data/vendor/cybozulib/include/cybozu/exception.hpp +253 -0
- data/vendor/cybozulib/include/cybozu/file.hpp +626 -0
- data/vendor/cybozulib/include/cybozu/fmindex.hpp +291 -0
- data/vendor/cybozulib/include/cybozu/format.hpp +93 -0
- data/vendor/cybozulib/include/cybozu/frequency.hpp +264 -0
- data/vendor/cybozulib/include/cybozu/hash.hpp +67 -0
- data/vendor/cybozulib/include/cybozu/inttype.hpp +174 -0
- data/vendor/cybozulib/include/cybozu/itoa.hpp +336 -0
- data/vendor/cybozulib/include/cybozu/json.hpp +120 -0
- data/vendor/cybozulib/include/cybozu/line_stream.hpp +149 -0
- data/vendor/cybozulib/include/cybozu/link_libeay32.hpp +21 -0
- data/vendor/cybozulib/include/cybozu/link_mpir.hpp +18 -0
- data/vendor/cybozulib/include/cybozu/link_ssleay32.hpp +19 -0
- data/vendor/cybozulib/include/cybozu/log.hpp +237 -0
- data/vendor/cybozulib/include/cybozu/minixml.hpp +452 -0
- data/vendor/cybozulib/include/cybozu/mmap.hpp +143 -0
- data/vendor/cybozulib/include/cybozu/mutex.hpp +144 -0
- data/vendor/cybozulib/include/cybozu/nlp/mecab.hpp +96 -0
- data/vendor/cybozulib/include/cybozu/nlp/plsi.hpp +315 -0
- data/vendor/cybozulib/include/cybozu/nlp/random.hpp +74 -0
- data/vendor/cybozulib/include/cybozu/nlp/sparse.hpp +529 -0
- data/vendor/cybozulib/include/cybozu/nlp/svd.hpp +486 -0
- data/vendor/cybozulib/include/cybozu/nlp/tfidf.hpp +226 -0
- data/vendor/cybozulib/include/cybozu/nlp/top_score.hpp +75 -0
- data/vendor/cybozulib/include/cybozu/option.hpp +743 -0
- data/vendor/cybozulib/include/cybozu/parallel.hpp +88 -0
- data/vendor/cybozulib/include/cybozu/pcg.hpp +72 -0
- data/vendor/cybozulib/include/cybozu/process.hpp +324 -0
- data/vendor/cybozulib/include/cybozu/quit_signal_handler.hpp +66 -0
- data/vendor/cybozulib/include/cybozu/random_generator.hpp +144 -0
- data/vendor/cybozulib/include/cybozu/regex.hpp +463 -0
- data/vendor/cybozulib/include/cybozu/select8.hpp +279 -0
- data/vendor/cybozulib/include/cybozu/serializer.hpp +363 -0
- data/vendor/cybozulib/include/cybozu/sha1.hpp +209 -0
- data/vendor/cybozulib/include/cybozu/sha2.hpp +506 -0
- data/vendor/cybozulib/include/cybozu/siphash.hpp +105 -0
- data/vendor/cybozulib/include/cybozu/socket.hpp +785 -0
- data/vendor/cybozulib/include/cybozu/ssl.hpp +203 -0
- data/vendor/cybozulib/include/cybozu/stacktrace.hpp +291 -0
- data/vendor/cybozulib/include/cybozu/stream.hpp +269 -0
- data/vendor/cybozulib/include/cybozu/string.hpp +1746 -0
- data/vendor/cybozulib/include/cybozu/string_operation.hpp +365 -0
- data/vendor/cybozulib/include/cybozu/sucvector.hpp +378 -0
- data/vendor/cybozulib/include/cybozu/test.hpp +373 -0
- data/vendor/cybozulib/include/cybozu/thread.hpp +229 -0
- data/vendor/cybozulib/include/cybozu/time.hpp +281 -0
- data/vendor/cybozulib/include/cybozu/tls.hpp +115 -0
- data/vendor/cybozulib/include/cybozu/unordered_map.hpp +13 -0
- data/vendor/cybozulib/include/cybozu/unordered_set.hpp +13 -0
- data/vendor/cybozulib/include/cybozu/v128.hpp +376 -0
- data/vendor/cybozulib/include/cybozu/wavelet_matrix.hpp +345 -0
- data/vendor/cybozulib/include/cybozu/xorshift.hpp +189 -0
- data/vendor/cybozulib/include/cybozu/zlib.hpp +325 -0
- data/vendor/cybozulib/include/sais.hxx +364 -0
- data/vendor/cybozulib/misc/make_select8tbl.cpp +26 -0
- data/vendor/cybozulib/mk.bat +37 -0
- data/vendor/cybozulib/readme.md +29 -0
- data/vendor/cybozulib/release.props +12 -0
- data/vendor/cybozulib/sample/Makefile +30 -0
- data/vendor/cybozulib/sample/csucvector_smpl.cpp +42 -0
- data/vendor/cybozulib/sample/data/svd/org/test1.S +4 -0
- data/vendor/cybozulib/sample/data/svd/org/test1.U +4 -0
- data/vendor/cybozulib/sample/data/svd/org/test1.V +6 -0
- data/vendor/cybozulib/sample/data/svd/test1 +4 -0
- data/vendor/cybozulib/sample/data/svd/test2 +4 -0
- data/vendor/cybozulib/sample/desymbol.cpp +127 -0
- data/vendor/cybozulib/sample/exception_smpl.cpp +46 -0
- data/vendor/cybozulib/sample/fmindex_smpl.cpp +231 -0
- data/vendor/cybozulib/sample/log_smpl.cpp +19 -0
- data/vendor/cybozulib/sample/mecab_smpl.cpp +37 -0
- data/vendor/cybozulib/sample/option2_smpl.cpp +68 -0
- data/vendor/cybozulib/sample/option_smpl.cpp +42 -0
- data/vendor/cybozulib/sample/plsi_smpl.cpp +207 -0
- data/vendor/cybozulib/sample/proj/exception_smpl.vcproj +184 -0
- data/vendor/cybozulib/sample/proj/mecab_smpl.vcproj +184 -0
- data/vendor/cybozulib/sample/proj/ssl_smpl/ssl_smpl.vcxproj +85 -0
- data/vendor/cybozulib/sample/proj/ssl_smpl.vcproj +347 -0
- data/vendor/cybozulib/sample/proj/stacktrace_smpl/stacktrace_smpl.vcxproj +85 -0
- data/vendor/cybozulib/sample/proj/svd_smpl.vcproj +184 -0
- data/vendor/cybozulib/sample/quit_signal_handler.cpp +30 -0
- data/vendor/cybozulib/sample/serializer_smpl.cpp +196 -0
- data/vendor/cybozulib/sample/socket_smpl.cpp +82 -0
- data/vendor/cybozulib/sample/ssl_smpl.cpp +39 -0
- data/vendor/cybozulib/sample/stacktrace_smpl.cpp +52 -0
- data/vendor/cybozulib/sample/svd_bench_smpl.cpp +143 -0
- data/vendor/cybozulib/sample/svd_smpl.cpp +94 -0
- data/vendor/cybozulib/sample/wm_bench_smpl.cpp +182 -0
- data/vendor/cybozulib/sample/zlib_smpl.cpp +41 -0
- data/vendor/cybozulib/src/Makefile +8 -0
- data/vendor/cybozulib/src/base/Makefile +19 -0
- data/vendor/cybozulib/test/Makefile +12 -0
- data/vendor/cybozulib/test/base/Makefile +37 -0
- data/vendor/cybozulib/test/base/array_test.cpp +173 -0
- data/vendor/cybozulib/test/base/atoi_test.cpp +774 -0
- data/vendor/cybozulib/test/base/atomic_test.cpp +49 -0
- data/vendor/cybozulib/test/base/base64_test.cpp +113 -0
- data/vendor/cybozulib/test/base/bit_operation_test.cpp +134 -0
- data/vendor/cybozulib/test/base/bitvector_test.cpp +204 -0
- data/vendor/cybozulib/test/base/condition_variable_cs_test.cpp +92 -0
- data/vendor/cybozulib/test/base/condition_variable_test.cpp +88 -0
- data/vendor/cybozulib/test/base/config_test.cpp +236 -0
- data/vendor/cybozulib/test/base/crypto_test.cpp +122 -0
- data/vendor/cybozulib/test/base/csucvector_test.cpp +63 -0
- data/vendor/cybozulib/test/base/csv_test.cpp +182 -0
- data/vendor/cybozulib/test/base/data/a.xml +26 -0
- data/vendor/cybozulib/test/base/endian_test.cpp +56 -0
- data/vendor/cybozulib/test/base/env_test.cpp +22 -0
- data/vendor/cybozulib/test/base/event_test.cpp +41 -0
- data/vendor/cybozulib/test/base/file_test.cpp +233 -0
- data/vendor/cybozulib/test/base/fmindex_test.cpp +118 -0
- data/vendor/cybozulib/test/base/format_test.cpp +12 -0
- data/vendor/cybozulib/test/base/frequency_test.cpp +104 -0
- data/vendor/cybozulib/test/base/itoa_test.cpp +522 -0
- data/vendor/cybozulib/test/base/line_stream_test.cpp +208 -0
- data/vendor/cybozulib/test/base/mecab_test.cpp +41 -0
- data/vendor/cybozulib/test/base/minixml_test.cpp +103 -0
- data/vendor/cybozulib/test/base/mmap_test.cpp +15 -0
- data/vendor/cybozulib/test/base/option_test.cpp +487 -0
- data/vendor/cybozulib/test/base/parallel_test.cpp +48 -0
- data/vendor/cybozulib/test/base/proj/array_test/array_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/atoi_test/atoi_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/atomic_test/atomic_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/base64_test/base64_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/condition_variable_cs_test/condition_variable_cs_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/condition_variable_test/condition_variable_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/config_test/config_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/csv_test/csv_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/endian_test/endian_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/env_test/env_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/event_test/event_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/file_test/file_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/itoa_test/itoa_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/mecab_test/mecab_test.vcxproj +88 -0
- data/vendor/cybozulib/test/base/proj/minixml_test/minixml_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/mmap_test/mmap_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/serializer_test/serializer_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/sha1_test/sha1_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/stream_test/stream_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/string_operation_test/string_operation_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/string_test/string_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/thread_test/thread_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/time_test/time_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/tls_test/tls_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/zlib_test/zlib_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/random_generator_test.cpp +28 -0
- data/vendor/cybozulib/test/base/regex_test.cpp +74 -0
- data/vendor/cybozulib/test/base/serializer_test.cpp +483 -0
- data/vendor/cybozulib/test/base/sha1_test.cpp +61 -0
- data/vendor/cybozulib/test/base/sha2_test.cpp +191 -0
- data/vendor/cybozulib/test/base/siphash_test.cpp +33 -0
- data/vendor/cybozulib/test/base/socket_test.cpp +76 -0
- data/vendor/cybozulib/test/base/stream_test.cpp +101 -0
- data/vendor/cybozulib/test/base/string_operation_test.cpp +340 -0
- data/vendor/cybozulib/test/base/string_test.cpp +1705 -0
- data/vendor/cybozulib/test/base/sucvector_test.cpp +312 -0
- data/vendor/cybozulib/test/base/thread_test.cpp +62 -0
- data/vendor/cybozulib/test/base/time_test.cpp +164 -0
- data/vendor/cybozulib/test/base/tls_test.cpp +50 -0
- data/vendor/cybozulib/test/base/wavelet_matrix_test.cpp +145 -0
- data/vendor/cybozulib/test/base/zlib_test.cpp +371 -0
- data/vendor/cybozulib/test/nlp/Makefile +27 -0
- data/vendor/cybozulib/test/nlp/proj/random_test.vcproj +184 -0
- data/vendor/cybozulib/test/nlp/proj/sparse_test.vcproj +184 -0
- data/vendor/cybozulib/test/nlp/proj/svd_test.vcproj +184 -0
- data/vendor/cybozulib/test/nlp/random_test.cpp +62 -0
- data/vendor/cybozulib/test/nlp/sparse_test.cpp +347 -0
- data/vendor/cybozulib/test/nlp/svd_test.cpp +234 -0
- data/vendor/cybozulib/test/nlp/top_score_test.cpp +40 -0
- data/vendor/cybozulib/tool/create_vcproj.py +186 -0
- data/vendor/cybozulib/tool/vcproj_tmpl.py +185 -0
- data/vendor/msoffice/COPYRIGHT +27 -0
- data/vendor/msoffice/Makefile +29 -0
- data/vendor/msoffice/bin/64/msoc.dll +0 -0
- data/vendor/msoffice/bin/64/msocsample.exe +0 -0
- data/vendor/msoffice/bin/64/msoffice-crypt.exe +0 -0
- data/vendor/msoffice/bin/msoc.dll +0 -0
- data/vendor/msoffice/bin/msocsample.exe +0 -0
- data/vendor/msoffice/bin/msoffice-crypt.exe +0 -0
- data/vendor/msoffice/common.mk +71 -0
- data/vendor/msoffice/common.props +26 -0
- data/vendor/msoffice/debug.props +14 -0
- data/vendor/msoffice/include/attack.hpp +211 -0
- data/vendor/msoffice/include/cfb.hpp +777 -0
- data/vendor/msoffice/include/crypto_util.hpp +450 -0
- data/vendor/msoffice/include/custom_sha1.hpp +342 -0
- data/vendor/msoffice/include/decode.hpp +240 -0
- data/vendor/msoffice/include/encode.hpp +221 -0
- data/vendor/msoffice/include/make_dataspace.hpp +316 -0
- data/vendor/msoffice/include/msoc.h +129 -0
- data/vendor/msoffice/include/resource.hpp +7 -0
- data/vendor/msoffice/include/standard_encryption.hpp +145 -0
- data/vendor/msoffice/include/uint32vec.hpp +179 -0
- data/vendor/msoffice/include/util.hpp +212 -0
- data/vendor/msoffice/lib/.emptydir +0 -0
- data/vendor/msoffice/misc/decrypt-xls.vbs +46 -0
- data/vendor/msoffice/mk.bat +1 -0
- data/vendor/msoffice/mkdll.bat +3 -0
- data/vendor/msoffice/msoc.def +13 -0
- data/vendor/msoffice/msocsample.py +178 -0
- data/vendor/msoffice/msoffice12.sln +31 -0
- data/vendor/msoffice/readme.md +110 -0
- data/vendor/msoffice/release.props +28 -0
- data/vendor/msoffice/src/Makefile +19 -0
- data/vendor/msoffice/src/attack.cpp +124 -0
- data/vendor/msoffice/src/cfb_test.cpp +77 -0
- data/vendor/msoffice/src/minisample.c +54 -0
- data/vendor/msoffice/src/msocdll.cpp +276 -0
- data/vendor/msoffice/src/msocsample.c +136 -0
- data/vendor/msoffice/src/msoffice-crypt.cpp +219 -0
- data/vendor/msoffice/src/proj/attack/attack.vcxproj +88 -0
- data/vendor/msoffice/src/proj/main/msoffice-crypt.vcxproj +88 -0
- data/vendor/msoffice/src/sha1.cpp +234 -0
- data/vendor/msoffice/test/Makefile +20 -0
- data/vendor/msoffice/test/cfb_test.cpp +74 -0
- data/vendor/msoffice/test/hash_test.cpp +59 -0
- data/vendor/msoffice/test/proj/cfb/cfb_test.vcxproj +90 -0
- data/vendor/msoffice/test/proj/hash/hash_test.vcxproj +90 -0
- data/vendor/msoffice/test/sampl.bat +8 -0
- data/vendor/msoffice/test_all.py +46 -0
- data/vendor/update +4 -0
- metadata +351 -0
|
@@ -0,0 +1,785 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
/**
|
|
3
|
+
@file
|
|
4
|
+
@brief tiny socket class
|
|
5
|
+
|
|
6
|
+
@author MITSUNARI Shigeo(@herumi)
|
|
7
|
+
@author MITSUNARI Shigeo
|
|
8
|
+
@remark mingw requires -lws2_32 option
|
|
9
|
+
*/
|
|
10
|
+
#include <errno.h>
|
|
11
|
+
#include <assert.h>
|
|
12
|
+
#include <stdio.h>
|
|
13
|
+
#ifdef _WIN32
|
|
14
|
+
#ifndef WIN32_LEAN_AND_MEAN
|
|
15
|
+
#define WIN32_LEAN_AND_MEAN
|
|
16
|
+
#endif
|
|
17
|
+
#include <windows.h>
|
|
18
|
+
#include <winsock2.h>
|
|
19
|
+
#include <ws2tcpip.h> // for socklen_t
|
|
20
|
+
#ifdef _MSC_VER
|
|
21
|
+
#pragma comment(lib, "ws2_32.lib")
|
|
22
|
+
#pragma comment(lib, "iphlpapi.lib")
|
|
23
|
+
#pragma warning(push)
|
|
24
|
+
#pragma warning(disable : 4127) // constant condition
|
|
25
|
+
#endif
|
|
26
|
+
#else
|
|
27
|
+
#include <unistd.h>
|
|
28
|
+
#include <sys/socket.h>
|
|
29
|
+
#include <sys/ioctl.h>
|
|
30
|
+
#include <netinet/tcp.h>
|
|
31
|
+
#include <arpa/inet.h>
|
|
32
|
+
#include <netdb.h>
|
|
33
|
+
#include <memory.h>
|
|
34
|
+
#include <signal.h>
|
|
35
|
+
#endif
|
|
36
|
+
#ifndef NDEBUG
|
|
37
|
+
#include <stdio.h>
|
|
38
|
+
#endif
|
|
39
|
+
|
|
40
|
+
#include <cybozu/atomic.hpp>
|
|
41
|
+
#include <cybozu/exception.hpp>
|
|
42
|
+
#include <cybozu/itoa.hpp>
|
|
43
|
+
#include <string>
|
|
44
|
+
|
|
45
|
+
#ifdef __linux__
|
|
46
|
+
// #define CYBOZU_SOCKET_USE_EPOLL
|
|
47
|
+
#include <sys/epoll.h>
|
|
48
|
+
#endif
|
|
49
|
+
|
|
50
|
+
namespace cybozu {
|
|
51
|
+
|
|
52
|
+
#ifdef _MSC_VER
|
|
53
|
+
struct NetErrorNo : public cybozu::ErrorNo {
|
|
54
|
+
NetErrorNo(NativeErrorNo err)
|
|
55
|
+
: cybozu::ErrorNo(err)
|
|
56
|
+
{
|
|
57
|
+
}
|
|
58
|
+
NetErrorNo()
|
|
59
|
+
: cybozu::ErrorNo(WSAGetLastError())
|
|
60
|
+
{
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
#else
|
|
64
|
+
typedef cybozu::ErrorNo NetErrorNo;
|
|
65
|
+
#endif
|
|
66
|
+
|
|
67
|
+
#ifdef CYBOZU_SOCKET_USE_EPOLL
|
|
68
|
+
|
|
69
|
+
namespace experimental {
|
|
70
|
+
|
|
71
|
+
struct EpollEvent {
|
|
72
|
+
struct epoll_event ev_;
|
|
73
|
+
EpollEvent()
|
|
74
|
+
{
|
|
75
|
+
memset(&ev_, 0, sizeof(ev_));
|
|
76
|
+
}
|
|
77
|
+
void set(int fd, uint32_t events = EPOLLIN)
|
|
78
|
+
{
|
|
79
|
+
ev_.events = events;
|
|
80
|
+
ev_.data.fd = fd;
|
|
81
|
+
}
|
|
82
|
+
int getFd() const { return ev_.data.fd; }
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
class Epoll {
|
|
86
|
+
int efd_;
|
|
87
|
+
bool verify(const char *msg, int ret, int *err) const {
|
|
88
|
+
if (ret >= 0) return true;
|
|
89
|
+
if (err == 0) throw cybozu::Exception(msg) << cybozu::NetErrorNo();
|
|
90
|
+
*err = errno;
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
public:
|
|
94
|
+
Epoll() : efd_(-1) {}
|
|
95
|
+
bool init(int *err = 0)
|
|
96
|
+
{
|
|
97
|
+
efd_ = ::epoll_create1(0);
|
|
98
|
+
return verify("Epoll:init", efd_, err);
|
|
99
|
+
}
|
|
100
|
+
~Epoll()
|
|
101
|
+
{
|
|
102
|
+
if (efd_ >= 0) ::close(efd_);
|
|
103
|
+
}
|
|
104
|
+
/*
|
|
105
|
+
throw if err == NULL
|
|
106
|
+
*/
|
|
107
|
+
bool ctrl(int op, int fd, EpollEvent *ev, int *err = 0) {
|
|
108
|
+
int ret = ::epoll_ctl(efd_, op, fd, &ev->ev_);
|
|
109
|
+
return verify("Epoll:ctrl", ret, err);
|
|
110
|
+
}
|
|
111
|
+
bool add(int fd, uint32_t events = EPOLLIN, int *err = 0) {
|
|
112
|
+
EpollEvent ev;
|
|
113
|
+
ev.set(fd, events);
|
|
114
|
+
return ctrl(EPOLL_CTL_ADD, fd, &ev, err);
|
|
115
|
+
}
|
|
116
|
+
bool del(int fd, int *err = 0) {
|
|
117
|
+
return ctrl(EPOLL_CTL_DEL, fd, NULL, err);
|
|
118
|
+
}
|
|
119
|
+
/*
|
|
120
|
+
msec : 0 : block
|
|
121
|
+
*/
|
|
122
|
+
int wait(EpollEvent *ev, int maxEv, int msec = 0)
|
|
123
|
+
{
|
|
124
|
+
/*
|
|
125
|
+
0 : return immediately
|
|
126
|
+
-1 : block indefinitely
|
|
127
|
+
*/
|
|
128
|
+
if (msec == 0) {
|
|
129
|
+
msec = -1;
|
|
130
|
+
} else if (msec == -1) {
|
|
131
|
+
msec = 0;
|
|
132
|
+
}
|
|
133
|
+
int ret = ::epoll_wait(efd_, &ev->ev_, maxEv, msec);
|
|
134
|
+
if (ret == 0) return 0; // timeout
|
|
135
|
+
if (ret < 0) return -errno;
|
|
136
|
+
return ret;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
struct AutoLock {
|
|
141
|
+
Epoll& ep_;
|
|
142
|
+
int fd_;
|
|
143
|
+
AutoLock(Epoll& ep, int fd, int events = EPOLLIN)
|
|
144
|
+
: ep_(ep)
|
|
145
|
+
, fd_(fd)
|
|
146
|
+
{
|
|
147
|
+
ep_.add(fd, events);
|
|
148
|
+
}
|
|
149
|
+
~AutoLock()
|
|
150
|
+
{
|
|
151
|
+
int err;
|
|
152
|
+
ep_.del(fd_, &err);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
} // cybozu::experimental
|
|
157
|
+
#endif
|
|
158
|
+
|
|
159
|
+
namespace ssl {
|
|
160
|
+
class ClientSocket;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
namespace socket_local {
|
|
164
|
+
|
|
165
|
+
#ifdef _WIN32
|
|
166
|
+
typedef SOCKET SocketHandle;
|
|
167
|
+
#else
|
|
168
|
+
typedef int SocketHandle;
|
|
169
|
+
#endif
|
|
170
|
+
|
|
171
|
+
struct InitTerm {
|
|
172
|
+
/** call once for init */
|
|
173
|
+
InitTerm()
|
|
174
|
+
{
|
|
175
|
+
#ifdef _WIN32
|
|
176
|
+
WSADATA data;
|
|
177
|
+
int err = ::WSAStartup(MAKEWORD(2, 2), &data);
|
|
178
|
+
if (err) {
|
|
179
|
+
fprintf(stderr, "WSAStartup failed : %d\n", err);
|
|
180
|
+
exit(1);
|
|
181
|
+
}
|
|
182
|
+
#else
|
|
183
|
+
::signal(SIGPIPE, SIG_IGN);
|
|
184
|
+
#endif
|
|
185
|
+
}
|
|
186
|
+
/** call once for term */
|
|
187
|
+
~InitTerm()
|
|
188
|
+
{
|
|
189
|
+
#ifdef _WIN32
|
|
190
|
+
::WSACleanup();
|
|
191
|
+
#endif
|
|
192
|
+
}
|
|
193
|
+
void dummyCall() { }
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
template<int dummy = 0>
|
|
197
|
+
struct InstanceIsHere { static InitTerm it_; };
|
|
198
|
+
|
|
199
|
+
template<int dummy>
|
|
200
|
+
InitTerm InstanceIsHere<dummy>::it_;
|
|
201
|
+
|
|
202
|
+
struct DummyCall {
|
|
203
|
+
DummyCall() { InstanceIsHere<>::it_.dummyCall(); }
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
} // cybozu::socket_local
|
|
207
|
+
|
|
208
|
+
class SocketAddr {
|
|
209
|
+
union {
|
|
210
|
+
// http://www.coins.tsukuba.ac.jp/~syspro/2010/No6_files/sockaddr.html
|
|
211
|
+
struct sockaddr sa; /* 16byte */
|
|
212
|
+
struct sockaddr_in v4; /* 16byte */
|
|
213
|
+
struct sockaddr_in6 v6;
|
|
214
|
+
} addr_;
|
|
215
|
+
socklen_t addrlen_;
|
|
216
|
+
int family_;
|
|
217
|
+
friend class Socket;
|
|
218
|
+
void verify() // call in only Socket::accept
|
|
219
|
+
{
|
|
220
|
+
if (addrlen_ == sizeof(addr_.v4) && addr_.sa.sa_family == AF_INET) {
|
|
221
|
+
family_ = AF_INET;
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (addrlen_ == sizeof(addr_.v6) && addr_.sa.sa_family == AF_INET6) {
|
|
225
|
+
family_ = AF_INET6;
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
throw cybozu::Exception("cybozu:SocketAddr:verify") << addrlen_;
|
|
229
|
+
}
|
|
230
|
+
public:
|
|
231
|
+
SocketAddr()
|
|
232
|
+
: addrlen_(0)
|
|
233
|
+
, family_(0)
|
|
234
|
+
{
|
|
235
|
+
}
|
|
236
|
+
SocketAddr(const std::string& address, uint16_t port, bool forceIpV6 = false)
|
|
237
|
+
{
|
|
238
|
+
set(address, port, forceIpV6);
|
|
239
|
+
}
|
|
240
|
+
void set(const std::string& address, uint16_t port, bool forceIpV6 = false)
|
|
241
|
+
{
|
|
242
|
+
char portStr[16];
|
|
243
|
+
CYBOZU_SNPRINTF(portStr, sizeof(portStr), "%d", port);
|
|
244
|
+
memset(&addr_, 0, sizeof(addr_));
|
|
245
|
+
addrlen_ = 0;
|
|
246
|
+
family_ = 0;
|
|
247
|
+
|
|
248
|
+
struct addrinfo *result = 0;
|
|
249
|
+
struct addrinfo hints;
|
|
250
|
+
memset(&hints, 0, sizeof(struct addrinfo));
|
|
251
|
+
hints.ai_family = AF_INET;
|
|
252
|
+
hints.ai_socktype = SOCK_STREAM;
|
|
253
|
+
hints.ai_protocol = IPPROTO_TCP;
|
|
254
|
+
hints.ai_flags = AI_NUMERICSERV; // AI_PASSIVE;
|
|
255
|
+
const int s = getaddrinfo(address.c_str(), portStr, &hints, &result);
|
|
256
|
+
// s == EAI_AGAIN
|
|
257
|
+
if (s || forceIpV6) {
|
|
258
|
+
hints.ai_family = AF_INET6;
|
|
259
|
+
hints.ai_flags |= AI_V4MAPPED;
|
|
260
|
+
if (getaddrinfo(address.c_str(), portStr, &hints, &result)) {
|
|
261
|
+
goto ERR_EXIT;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
{
|
|
265
|
+
bool found = false;
|
|
266
|
+
for (const struct addrinfo *p = result; p; p = p->ai_next) {
|
|
267
|
+
const int family = p->ai_family;
|
|
268
|
+
if (family == hints.ai_family) {
|
|
269
|
+
if (p->ai_addrlen > sizeof(addr_)) {
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
memcpy(&addr_, p->ai_addr, p->ai_addrlen);
|
|
273
|
+
addrlen_ = (socklen_t)p->ai_addrlen;
|
|
274
|
+
family_ = family;
|
|
275
|
+
found = true;
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
freeaddrinfo(result);
|
|
280
|
+
if (found) return;
|
|
281
|
+
}
|
|
282
|
+
ERR_EXIT:
|
|
283
|
+
throw cybozu::Exception("SocketAddr:set") << address << port << cybozu::NetErrorNo();
|
|
284
|
+
}
|
|
285
|
+
socklen_t getSize() const { return addrlen_; }
|
|
286
|
+
int getFamily() const { return family_; }
|
|
287
|
+
const struct sockaddr *get() const { return &addr_.sa; }
|
|
288
|
+
uint16_t getPort() const {
|
|
289
|
+
if (family_ == AF_INET) {
|
|
290
|
+
return ntohs(addr_.v4.sin_port);
|
|
291
|
+
} else if (family_ == AF_INET6) {
|
|
292
|
+
return ntohs(addr_.v6.sin6_port);
|
|
293
|
+
}
|
|
294
|
+
throw cybozu::Exception("SocketAddr:getPort:bad family") << family_;
|
|
295
|
+
}
|
|
296
|
+
// compare addr without port
|
|
297
|
+
bool hasSameAddr(const SocketAddr& rhs) const
|
|
298
|
+
{
|
|
299
|
+
const uint8_t *v4 = 0;
|
|
300
|
+
const uint8_t *v6 = 0;
|
|
301
|
+
if (family_ == AF_INET) {
|
|
302
|
+
if (rhs.family_ == AF_INET) return memcmp(&addr_.v4.sin_addr, &rhs.addr_.v4.sin_addr, sizeof(in_addr)) == 0;
|
|
303
|
+
if (rhs.family_ != AF_INET6) return false;
|
|
304
|
+
v4 = (const uint8_t*)&addr_.v4.sin_addr;
|
|
305
|
+
v6 = (const uint8_t*)&rhs.addr_.v6.sin6_addr;
|
|
306
|
+
} else if (family_ != AF_INET6) {
|
|
307
|
+
return false;
|
|
308
|
+
} else {
|
|
309
|
+
if (rhs.family_ == AF_INET6) return memcmp(&addr_.v6.sin6_addr, &rhs.addr_.v6.sin6_addr, sizeof(in6_addr)) == 0;
|
|
310
|
+
if (rhs.family_ != AF_INET) return false;
|
|
311
|
+
v4 = (const uint8_t*)&rhs.addr_.v4.sin_addr;
|
|
312
|
+
v6 = (const uint8_t*)&addr_.v6.sin6_addr;
|
|
313
|
+
}
|
|
314
|
+
// Ipv6-mapped?
|
|
315
|
+
const uint8_t header[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
|
316
|
+
return memcmp(v6, header, 12) == 0 && memcmp(v6 + 12, v4, 4) == 0;
|
|
317
|
+
}
|
|
318
|
+
std::string toStr() const
|
|
319
|
+
{
|
|
320
|
+
if (family_ == AF_INET || family_ == AF_INET6) {
|
|
321
|
+
char buf[INET6_ADDRSTRLEN];
|
|
322
|
+
assert(INET_ADDRSTRLEN <= INET6_ADDRSTRLEN);
|
|
323
|
+
const bool isIPv4 = family_ == AF_INET;
|
|
324
|
+
const void *pa = isIPv4 ? (const void*)&addr_.v4.sin_addr : (const void*)&addr_.v6.sin6_addr;
|
|
325
|
+
// not "const void*" because of vc
|
|
326
|
+
const char *p = inet_ntop(family_, const_cast<void*>(pa), buf, sizeof(buf));
|
|
327
|
+
if (!p) throw cybozu::Exception("cybozu:SocketAddr:toStr") << cybozu::NetErrorNo();
|
|
328
|
+
if (isIPv4) return std::string(p) + ':' + cybozu::itoa(getPort());
|
|
329
|
+
return std::string("[") + p + "]:" + cybozu::itoa(getPort());
|
|
330
|
+
}
|
|
331
|
+
throw cybozu::Exception("cybozu:SocketAddr:toStr:bad family_") << family_;
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
/*
|
|
335
|
+
socket class
|
|
336
|
+
@note ower is moved if copied
|
|
337
|
+
*/
|
|
338
|
+
class Socket {
|
|
339
|
+
friend class cybozu::ssl::ClientSocket;
|
|
340
|
+
private:
|
|
341
|
+
cybozu::socket_local::SocketHandle sd_;
|
|
342
|
+
Socket(const Socket&);
|
|
343
|
+
void operator=(const Socket&);
|
|
344
|
+
#ifdef WIN32
|
|
345
|
+
void setTimeout(int type, int msec)
|
|
346
|
+
{
|
|
347
|
+
setSocketOption(type, msec);
|
|
348
|
+
}
|
|
349
|
+
/* return msec */
|
|
350
|
+
int getTimeout(int type) const
|
|
351
|
+
{
|
|
352
|
+
return getSocketOption(type);
|
|
353
|
+
}
|
|
354
|
+
#else
|
|
355
|
+
void setTimeout(int type, int msec)
|
|
356
|
+
{
|
|
357
|
+
struct timeval t;
|
|
358
|
+
t.tv_sec = msec / 1000;
|
|
359
|
+
t.tv_usec = (msec % 1000) * 1000;
|
|
360
|
+
setSocketOption(type, t);
|
|
361
|
+
}
|
|
362
|
+
/* return msec */
|
|
363
|
+
int getTimeout(int type) const
|
|
364
|
+
{
|
|
365
|
+
struct timeval t;
|
|
366
|
+
getSocketOption(type, &t);
|
|
367
|
+
return t.tv_sec * 1000 + t.tv_usec / 1000; /* msec */
|
|
368
|
+
}
|
|
369
|
+
#endif
|
|
370
|
+
void setBlocking(bool isBlocking)
|
|
371
|
+
{
|
|
372
|
+
#ifdef _WIN32
|
|
373
|
+
u_long val = isBlocking ? 0 : 1;
|
|
374
|
+
int ret = ::ioctlsocket(sd_, FIONBIO, &val);
|
|
375
|
+
#else
|
|
376
|
+
int val = isBlocking ? 0 : 1;
|
|
377
|
+
int ret = ::ioctl(sd_, FIONBIO, &val);
|
|
378
|
+
#endif
|
|
379
|
+
if (ret < 0) throw cybozu::Exception("Socket:setBlocking") << cybozu::NetErrorNo() << isBlocking;
|
|
380
|
+
}
|
|
381
|
+
public:
|
|
382
|
+
#ifndef _WIN32
|
|
383
|
+
static const int INVALID_SOCKET = -1;
|
|
384
|
+
#endif
|
|
385
|
+
Socket()
|
|
386
|
+
: sd_(INVALID_SOCKET)
|
|
387
|
+
{
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
bool isValid() const { return sd_ != INVALID_SOCKET; }
|
|
391
|
+
|
|
392
|
+
// move
|
|
393
|
+
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
|
|
394
|
+
Socket(Socket&& rhs)
|
|
395
|
+
: sd_(INVALID_SOCKET)
|
|
396
|
+
{
|
|
397
|
+
sd_ = cybozu::AtomicExchange(&rhs.sd_, sd_);
|
|
398
|
+
}
|
|
399
|
+
#endif
|
|
400
|
+
// close and move
|
|
401
|
+
void moveFrom(Socket& rhs)
|
|
402
|
+
{
|
|
403
|
+
close();
|
|
404
|
+
sd_ = cybozu::AtomicExchange(&rhs.sd_, INVALID_SOCKET);
|
|
405
|
+
}
|
|
406
|
+
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
|
|
407
|
+
void operator=(Socket&& rhs)
|
|
408
|
+
#else
|
|
409
|
+
void operator=(Socket& rhs)
|
|
410
|
+
#endif
|
|
411
|
+
{
|
|
412
|
+
moveFrom(rhs);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
~Socket()
|
|
416
|
+
{
|
|
417
|
+
close(cybozu::DontThrow);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
bool close(bool dontThrow = false)
|
|
421
|
+
{
|
|
422
|
+
cybozu::socket_local::SocketHandle sd = cybozu::AtomicExchange(&sd_, INVALID_SOCKET);
|
|
423
|
+
if (sd == INVALID_SOCKET) return true;
|
|
424
|
+
#ifdef _WIN32
|
|
425
|
+
// ::shutdown(sd, SD_SEND);
|
|
426
|
+
// shutdown is called in closesocket
|
|
427
|
+
bool isOK = ::closesocket(sd) == 0;
|
|
428
|
+
#else
|
|
429
|
+
bool isOK = ::close(sd) == 0;
|
|
430
|
+
#endif
|
|
431
|
+
if (!dontThrow && !isOK) throw cybozu::Exception("Socket:close") << cybozu::NetErrorNo();
|
|
432
|
+
return isOK;
|
|
433
|
+
}
|
|
434
|
+
/*
|
|
435
|
+
how 0 : SHUTRD ; disallow read
|
|
436
|
+
1 : SHUT_WR ; disallow write
|
|
437
|
+
2 : SHUT_RDWR ; disallow read/write
|
|
438
|
+
*/
|
|
439
|
+
bool shutdown(int how, bool dontThrow = false)
|
|
440
|
+
{
|
|
441
|
+
bool isOK = ::shutdown(sd_, how) == 0;
|
|
442
|
+
if (!dontThrow && !isOK) throw cybozu::Exception("Socket:waitForClose:shutdown") << cybozu::NetErrorNo();
|
|
443
|
+
return isOK;
|
|
444
|
+
}
|
|
445
|
+
/*
|
|
446
|
+
send FIN and wait for remote's close().
|
|
447
|
+
this function is used for the following situation.
|
|
448
|
+
sock.write()
|
|
449
|
+
sock.waitForClose()
|
|
450
|
+
sock.close()
|
|
451
|
+
*/
|
|
452
|
+
void waitForClose()
|
|
453
|
+
{
|
|
454
|
+
if (sd_ == INVALID_SOCKET) return;
|
|
455
|
+
// send FIN and this socket can't write any data.
|
|
456
|
+
shutdown(1);
|
|
457
|
+
// wait for FIN from the peer.
|
|
458
|
+
char buf[1];
|
|
459
|
+
ssize_t readSize = readSome(buf, sizeof(buf));
|
|
460
|
+
if (readSize != 0) {
|
|
461
|
+
throw cybozu::Exception("Socket:waitForClose:readSome:bad size") << readSize;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/*!
|
|
466
|
+
receive data
|
|
467
|
+
@param buf [out] receive buffer
|
|
468
|
+
@param bufSize [in] receive buffer size(byte)
|
|
469
|
+
@note return read size
|
|
470
|
+
*/
|
|
471
|
+
size_t readSome(void *buf, size_t bufSize)
|
|
472
|
+
{
|
|
473
|
+
int size = (int)(std::min)((size_t)0x7fffffff, bufSize);
|
|
474
|
+
#ifdef _WIN32
|
|
475
|
+
int readSize = ::recv(sd_, (char *)buf, size, 0);
|
|
476
|
+
#else
|
|
477
|
+
RETRY:
|
|
478
|
+
ssize_t readSize = ::read(sd_, buf, size);
|
|
479
|
+
if (readSize < 0 && errno == EINTR) goto RETRY;
|
|
480
|
+
#endif
|
|
481
|
+
if (readSize < 0) throw cybozu::Exception("Socket:readSome") << cybozu::NetErrorNo() << bufSize;
|
|
482
|
+
return readSize;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/*!
|
|
486
|
+
receive all data unless timeout
|
|
487
|
+
@param buf [out] receive buffer
|
|
488
|
+
@param bufSize [in] receive buffer size(byte)
|
|
489
|
+
*/
|
|
490
|
+
void read(void *buf, size_t bufSize)
|
|
491
|
+
{
|
|
492
|
+
char *p = (char *)buf;
|
|
493
|
+
while (bufSize > 0) {
|
|
494
|
+
size_t readSize = readSome(p, bufSize);
|
|
495
|
+
if (readSize == 0) throw cybozu::Exception("Socket:read:readSize is zero");
|
|
496
|
+
p += readSize;
|
|
497
|
+
bufSize -= readSize;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
/*!
|
|
501
|
+
write all data
|
|
502
|
+
@param buf [out] send buffer
|
|
503
|
+
@param bufSize [in] send buffer size(byte)
|
|
504
|
+
*/
|
|
505
|
+
void write(bool *pb, const void *buf, size_t bufSize)
|
|
506
|
+
{
|
|
507
|
+
const char *p = (const char *)buf;
|
|
508
|
+
while (bufSize > 0) {
|
|
509
|
+
int size = (int)(std::min)(size_t(0x7fffffff), bufSize);
|
|
510
|
+
#ifdef _WIN32
|
|
511
|
+
int writeSize = ::send(sd_, p, size, 0);
|
|
512
|
+
#else
|
|
513
|
+
int writeSize = ::write(sd_, p, size);
|
|
514
|
+
if (writeSize < 0 && errno == EINTR) continue;
|
|
515
|
+
#endif
|
|
516
|
+
if (writeSize < 0) {
|
|
517
|
+
*pb = false;
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
p += writeSize;
|
|
521
|
+
bufSize -= writeSize;
|
|
522
|
+
}
|
|
523
|
+
*pb = true;
|
|
524
|
+
}
|
|
525
|
+
void write(const void *buf, size_t bufSize)
|
|
526
|
+
{
|
|
527
|
+
bool b;
|
|
528
|
+
write(&b, buf, bufSize);
|
|
529
|
+
if (!b) throw cybozu::Exception("Socket:write") << cybozu::NetErrorNo() << bufSize;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
connect to address:port
|
|
533
|
+
@param address [in] address
|
|
534
|
+
@param port [in] port
|
|
535
|
+
@param msec: 0 : block
|
|
536
|
+
*/
|
|
537
|
+
void connect(const std::string& address, uint16_t port, int msec = 0)
|
|
538
|
+
{
|
|
539
|
+
SocketAddr addr;
|
|
540
|
+
addr.set(address, port);
|
|
541
|
+
connect(addr, msec);
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
connect to resolved socket addr
|
|
545
|
+
*/
|
|
546
|
+
void connect(const cybozu::SocketAddr& addr, int msec = 0)
|
|
547
|
+
{
|
|
548
|
+
if (isValid()) throw cybozu::Exception("Socket:connect:already connect");
|
|
549
|
+
sd_ = ::socket(addr.getFamily(), SOCK_STREAM, IPPROTO_TCP);
|
|
550
|
+
if (!isValid()) {
|
|
551
|
+
throw cybozu::Exception("Socket:connect:socket") << cybozu::NetErrorNo();
|
|
552
|
+
}
|
|
553
|
+
if (msec == 0) {
|
|
554
|
+
if (::connect(sd_, addr.get(), addr.getSize()) < 0) {
|
|
555
|
+
throw cybozu::Exception("Socket:connect") << cybozu::NetErrorNo() << addr.toStr();
|
|
556
|
+
}
|
|
557
|
+
} else {
|
|
558
|
+
setBlocking(false);
|
|
559
|
+
if (::connect(sd_, addr.get(), addr.getSize()) < 0) {
|
|
560
|
+
#ifdef _WIN32
|
|
561
|
+
bool inProgress = WSAGetLastError() == WSAEWOULDBLOCK;
|
|
562
|
+
#else
|
|
563
|
+
bool inProgress = errno == EINPROGRESS;
|
|
564
|
+
#endif
|
|
565
|
+
if (!inProgress) throw cybozu::Exception("Socket:connect:not in progress") << cybozu::NetErrorNo() << addr.toStr();
|
|
566
|
+
if (!queryAccept(msec, false)) throw cybozu::Exception("Socket:connect:timeout") << addr.toStr();
|
|
567
|
+
int err = getSocketOption(SO_ERROR);
|
|
568
|
+
if (err != 0) throw cybozu::Exception("Socket::connect:bad socket") << cybozu::NetErrorNo(err);
|
|
569
|
+
}
|
|
570
|
+
setBlocking(true);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
static const int allowIPv4 = 1;
|
|
575
|
+
static const int allowIPv6 = 2;
|
|
576
|
+
/**
|
|
577
|
+
init for server
|
|
578
|
+
@param port [in] port number
|
|
579
|
+
*/
|
|
580
|
+
void bind(uint16_t port, int mode = allowIPv4 | allowIPv6)
|
|
581
|
+
{
|
|
582
|
+
const int family = (mode & allowIPv6) ? AF_INET6 : AF_INET;
|
|
583
|
+
sd_ = ::socket(family, SOCK_STREAM, IPPROTO_TCP);
|
|
584
|
+
if (!isValid()) {
|
|
585
|
+
throw cybozu::Exception("Socket:bind:socket") << cybozu::NetErrorNo();
|
|
586
|
+
}
|
|
587
|
+
setSocketOption(SO_REUSEADDR, 1);
|
|
588
|
+
struct sockaddr_in6 addr6;
|
|
589
|
+
struct sockaddr_in addr4;
|
|
590
|
+
struct sockaddr *addr;
|
|
591
|
+
socklen_t addrLen;
|
|
592
|
+
if (mode & allowIPv6) {
|
|
593
|
+
setSocketOption(IPV6_V6ONLY, (mode & allowIPv4) ? 0 : 1, IPPROTO_IPV6);
|
|
594
|
+
memset(&addr6, 0, sizeof(addr6));
|
|
595
|
+
addr6.sin6_family = AF_INET6;
|
|
596
|
+
addr6.sin6_port = htons(port);
|
|
597
|
+
addr = (struct sockaddr*)&addr6;
|
|
598
|
+
addrLen = sizeof(addr6);
|
|
599
|
+
} else {
|
|
600
|
+
memset(&addr4, 0, sizeof(addr4));
|
|
601
|
+
addr4.sin_family = AF_INET;
|
|
602
|
+
addr4.sin_port = htons(port);
|
|
603
|
+
addr = (struct sockaddr*)&addr4;
|
|
604
|
+
addrLen = sizeof(addr4);
|
|
605
|
+
}
|
|
606
|
+
if (::bind(sd_, addr, addrLen) == 0) {
|
|
607
|
+
if (::listen(sd_, SOMAXCONN) == 0) {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
cybozu::NetErrorNo keep;
|
|
612
|
+
close(cybozu::DontThrow);
|
|
613
|
+
throw cybozu::Exception("Socket:bind") << keep;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
return positive if accepted
|
|
618
|
+
return zero if timeout
|
|
619
|
+
return negative(-errno) if error
|
|
620
|
+
*/
|
|
621
|
+
int queryAcceptNoThrow(int msec = 1000, bool checkWrite = true)
|
|
622
|
+
{
|
|
623
|
+
if (sd_ == INVALID_SOCKET) return -EBADF;
|
|
624
|
+
#ifdef CYBOZU_SOCKET_USE_EPOLL
|
|
625
|
+
int err;
|
|
626
|
+
experimental::Epoll ep;
|
|
627
|
+
if (!ep.init(&err)) return -err;
|
|
628
|
+
uint32_t events = checkWrite ? EPOLLIN : EPOLLOUT;
|
|
629
|
+
experimental::AutoLock al(ep, sd_, events);
|
|
630
|
+
experimental::EpollEvent ev;
|
|
631
|
+
int ret = ep.wait(&ev, 1, msec);
|
|
632
|
+
if (ret != 1) return ret;
|
|
633
|
+
assert(ev.getFd() == sd_);
|
|
634
|
+
return ret;
|
|
635
|
+
#else
|
|
636
|
+
#ifndef _WIN32
|
|
637
|
+
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms739169.aspx
|
|
638
|
+
if (sd_ >= FD_SETSIZE) return -EMFILE;
|
|
639
|
+
#endif
|
|
640
|
+
struct timeval timeout;
|
|
641
|
+
timeout.tv_sec = msec / 1000;
|
|
642
|
+
timeout.tv_usec = (msec % 1000) * 1000;
|
|
643
|
+
fd_set fds;
|
|
644
|
+
FD_ZERO(&fds);
|
|
645
|
+
FD_SET((unsigned)sd_, &fds);
|
|
646
|
+
int fdNum;
|
|
647
|
+
if (checkWrite) {
|
|
648
|
+
fdNum = ::select((int)sd_ + 1, &fds, 0, 0, &timeout);
|
|
649
|
+
} else {
|
|
650
|
+
fdNum = ::select((int)sd_ + 1, 0, &fds, 0, &timeout);
|
|
651
|
+
}
|
|
652
|
+
if (fdNum < 0) return -errno;
|
|
653
|
+
return fdNum;
|
|
654
|
+
#endif
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
return true if acceptable, otherwise false
|
|
658
|
+
return false if one second passed
|
|
659
|
+
while (!server.queryAccept()) {
|
|
660
|
+
}
|
|
661
|
+
client.accept(server);
|
|
662
|
+
*/
|
|
663
|
+
bool queryAccept(int msec = 1000, bool checkWrite = true)
|
|
664
|
+
{
|
|
665
|
+
int ret = queryAcceptNoThrow(msec, checkWrite);
|
|
666
|
+
if (ret < 0) throw cybozu::Exception("Socket:queryAccept") << cybozu::NetErrorNo(-ret);
|
|
667
|
+
return ret > 0;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
accept for server
|
|
672
|
+
*/
|
|
673
|
+
void accept(Socket& client, SocketAddr *paddr = 0) const
|
|
674
|
+
{
|
|
675
|
+
if (paddr) {
|
|
676
|
+
struct sockaddr *psa = &paddr->addr_.sa;
|
|
677
|
+
paddr->addrlen_ = sizeof(paddr->addr_);
|
|
678
|
+
client.sd_ = ::accept(sd_, psa, &paddr->addrlen_);
|
|
679
|
+
paddr->verify();
|
|
680
|
+
} else {
|
|
681
|
+
client.sd_ = ::accept(sd_, 0, 0);
|
|
682
|
+
}
|
|
683
|
+
if (!client.isValid()) throw cybozu::Exception("Socket:accept") << cybozu::NetErrorNo();
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
template<typename T>
|
|
687
|
+
void setSocketOption(int optname, const T& value, int level = SOL_SOCKET)
|
|
688
|
+
{
|
|
689
|
+
bool isOK = setsockopt(sd_, level, optname, cybozu::cast<const char*>(&value), sizeof(T)) == 0;
|
|
690
|
+
if (!isOK) throw cybozu::Exception("Socket:setSocketOption") << cybozu::NetErrorNo();
|
|
691
|
+
}
|
|
692
|
+
template<typename T>
|
|
693
|
+
void getSocketOption(int optname, T* value, int level = SOL_SOCKET) const
|
|
694
|
+
{
|
|
695
|
+
socklen_t len = (socklen_t)sizeof(T);
|
|
696
|
+
bool isOK = getsockopt(sd_, level, optname, cybozu::cast<char*>(value), &len) == 0;
|
|
697
|
+
if (!isOK) throw cybozu::Exception("Socket:getSocketOption") << cybozu::NetErrorNo();
|
|
698
|
+
}
|
|
699
|
+
int getSocketOption(int optname) const
|
|
700
|
+
{
|
|
701
|
+
int ret;
|
|
702
|
+
getSocketOption(optname, &ret);
|
|
703
|
+
return ret;
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
setup linger
|
|
707
|
+
*/
|
|
708
|
+
void setLinger(uint16_t l_onoff, uint16_t l_linger)
|
|
709
|
+
{
|
|
710
|
+
struct linger linger;
|
|
711
|
+
linger.l_onoff = l_onoff;
|
|
712
|
+
linger.l_linger = l_linger;
|
|
713
|
+
setSocketOption(SO_LINGER, &linger);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
get receive buffer size
|
|
717
|
+
@retval positive buffer size(byte)
|
|
718
|
+
@retval -1 error
|
|
719
|
+
*/
|
|
720
|
+
int getReceiveBufferSize() const
|
|
721
|
+
{
|
|
722
|
+
return getSocketOption(SO_RCVBUF);
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
set receive buffer size
|
|
726
|
+
@param size [in] buffer size(byte)
|
|
727
|
+
*/
|
|
728
|
+
void setReceiveBufferSize(int size)
|
|
729
|
+
{
|
|
730
|
+
setSocketOption(SO_RCVBUF, size);
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
get send buffer size
|
|
734
|
+
@retval positive buffer size(byte)
|
|
735
|
+
@retval -1 error
|
|
736
|
+
*/
|
|
737
|
+
int getSendBufferSize() const
|
|
738
|
+
{
|
|
739
|
+
return getSocketOption(SO_SNDBUF);
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
sed send buffer size
|
|
743
|
+
@param size [in] buffer size(byte)
|
|
744
|
+
*/
|
|
745
|
+
void setSendBufferSize(int size)
|
|
746
|
+
{
|
|
747
|
+
setSocketOption(SO_SNDBUF, size);
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
set send timeout
|
|
751
|
+
@param msec [in] msec
|
|
752
|
+
*/
|
|
753
|
+
void setSendTimeout(int msec)
|
|
754
|
+
{
|
|
755
|
+
setTimeout(SO_SNDTIMEO, msec);
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
set receive timeout
|
|
759
|
+
@param msec [in] msec
|
|
760
|
+
*/
|
|
761
|
+
void setReceiveTimeout(int msec)
|
|
762
|
+
{
|
|
763
|
+
setTimeout(SO_RCVTIMEO, msec);
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
get send timeout(msec)
|
|
767
|
+
*/
|
|
768
|
+
int getSendTimeout() const
|
|
769
|
+
{
|
|
770
|
+
return getTimeout(SO_SNDTIMEO);
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
get receive timeout(msec)
|
|
774
|
+
*/
|
|
775
|
+
int getReceiveTimeout() const
|
|
776
|
+
{
|
|
777
|
+
return getTimeout(SO_RCVTIMEO);
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
} // cybozu
|
|
782
|
+
|
|
783
|
+
#ifdef _MSC_VER
|
|
784
|
+
#pragma warning(pop)
|
|
785
|
+
#endif
|